home *** CD-ROM | disk | FTP | other *** search
/ Shareware Extravaganza - Disc 1 / ShareWare Extravaganza 1 of 4 (The Ultimate Shareware Company).iso / sblaster / tpu60b.zip / TPU6DOC.TXT < prev    next >
Text File  |  1991-04-16  |  129KB  |  2,980 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.                            -----------------------------
  18.  
  19.  
  20.  
  21.                            INSIDE TURBO PASCAL 6.0 UNITS
  22.  
  23.  
  24.  
  25.                            -----------------------------
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.                                          by
  50.  
  51.                                   William L. Peavy
  52.  
  53.                                  -----------------
  54.  
  55.                               Revised: April 16, 1991
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.                                       ABSTRACT
  63.  
  64.             If you  want to  know what is in a .TPU (unit) file produced
  65.             by Version  6.0 of  Turbo Pascal from Borland International,
  66.             then this  paper is  for you.    It  doesn't  explain  quite
  67.             everything since the I don't have access to secret documents
  68.             or anything  like that  and since  some of  the data in .TPU
  69.             files just doesn't have enough auxiliary information to make
  70.             its role  clear.   However, it  is possible to learn a great
  71.             deal about  how Turbo  Pascal organizes  the information  it
  72.             needs to  refer to,  and it  is also  possible to learn just
  73.             what kind of code the compiler produces.
  74.  
  75.             This is  the third  in a series of reports on the subject of
  76.             Turbo Pascal  Units, the  first treating  with Turbo  Pascal
  77.             Version 5.0  and the  second with  Turbo Pascal  5.5.    The
  78.             evolution  of   these  files   in  the   face  of   changing
  79.             requirements has  been fascinating to behold and deciphering
  80.             their contents has been challenging to say the least.
  81.  
  82.             The programs supplied with this report have been reorganized
  83.             from their  5.5 style in some ways and many identifiers have
  84.             been changed.   These  changes were  more for style than for
  85.             substance.   Other changes  were dictated  by the changes in
  86.             the organization  of the  TPU file itself and certain errors
  87.             in the 5.5 programs have been corrected.  In addition, other
  88.             errors of  interpretation have  been fixed  which has led to
  89.             some enhanced descriptive capability.
  90.  
  91.             Since I  have a "real" job which requires my full attention,
  92.             and since  it doesn't  involve use  of these products in any
  93.             direct way,  I am  usually hard-pressed to find the personal
  94.             time to  conduct this  research.    Consequently,  I  always
  95.             refuse to  commit to follow-up or even error correction.  It
  96.             would  be  irresponsible  of  me  to  pretend  it  could  be
  97.             otherwise.  Even so, this is a revised report which contains
  98.             a few  error fixes  and discusses the newly enhanced program
  99.             which incorporates  these fixes  and  sports  some  enhanced
  100.             capabilities.
  101.  
  102.  
  103.  
  104.                                       Contents
  105.  
  106.  
  107.  
  108.            Introduction ................................................. 5
  109.  
  110.            1. Gross File Structure ...................................... 5
  111.                1.1 User Units ........................................... 6
  112.  
  113.            2. Locators .................................................. 7
  114.                2.1 Local Links .......................................... 7
  115.                2.2 Global Links ......................................... 7
  116.                2.3 Table Offsets ........................................ 7
  117.                2.4 Basic Relationships .................................. 8
  118.  
  119.            3. Unit Header .............................................. 11
  120.                3.1 Description ......................................... 11
  121.                3.2 UNIT Size ........................................... 14
  122.  
  123.            4. Symbol Dictionaries ...................................... 14
  124.                4.1 Organization ........................................ 14
  125.                4.2 Interface Dictionary ................................ 14
  126.                4.3 Debug Dictionary .................................... 15
  127.                4.4 Dictionary Elements ................................. 15
  128.  
  129.                    4.4.1 Hash Tables ................................... 15
  130.                        4.4.1.1 Size .................................... 16
  131.                        4.4.1.2 Scope ................................... 16
  132.                        4.4.1.3 Special Cases ........................... 17
  133.  
  134.                    4.4.2 Dictionary Headers ............................ 17
  135.  
  136.                    4.4.3 Dictionary Stubs .............................. 18
  137.                        4.4.3.1 Label Declaratives ("O") ................ 18
  138.                        4.4.3.2 Un-Typed Constants ("P") ................ 18
  139.                        4.4.3.3 Named Types ("Q") ....................... 18
  140.                        4.4.3.4 Variables, Fields, Typed Cons ("R") ..... 19
  141.                        4.4.3.5 Subprograms & Methods ("S") ............. 20
  142.                        4.4.3.6 Turbo Std Procedures ("T") .............. 21
  143.                        4.4.3.7 Turbo Std Functions ("U") ............... 21
  144.                        4.4.3.8 Turbo Std "NEW" Routine ("V") ........... 21
  145.                        4.4.3.9 Turbo Std Port Arrays ("W") ............. 21
  146.                        4.4.3.10 Turbo Std External Variables ("X") ..... 21
  147.                        4.4.3.11 Units ("Y") ............................ 22
  148.  
  149.                    4.4.4 Type Descriptors .............................. 22
  150.                        4.4.4.1 Scope ................................... 23
  151.                        4.4.4.2 Prefix Part ............................. 23
  152.                        4.4.4.3 Suffix Parts ............................ 24
  153.                            4.4.4.3.1 Un-Typed .......................... 25
  154.                            4.4.4.3.2 Structured Types .................. 25
  155.                                4.4.4.3.2.1 ARRAY Types ................. 25
  156.                                4.4.4.3.2.2 RECORD Types ................ 25
  157.                                4.4.4.3.2.3 OBJECT Types ................ 26
  158.                                4.4.4.3.2.4 FILE (non-TEXT) Types ....... 27
  159.                                4.4.4.3.2.5 TEXT File Types ............. 27
  160.                                4.4.4.3.2.6 SET Types ................... 27
  161.  
  162.  
  163.  
  164.                                        - iii -
  165.  
  166.  
  167.  
  168.                                       Contents
  169.  
  170.  
  171.                                4.4.4.3.2.7 POINTER Types ............... 27
  172.                                4.4.4.3.2.8 STRING Types ................ 27
  173.                            4.4.4.3.3 Floating-Point Types .............. 27
  174.                            4.4.4.3.4 Ordinal Types ..................... 28
  175.                                4.4.4.3.4.1 "Integers" .................. 28
  176.                                4.4.4.3.4.2 BOOLEANs .................... 28
  177.                                4.4.4.3.4.3 CHARs ....................... 28
  178.                                4.4.4.3.4.4 ENUMERATions ................ 29
  179.                            4.4.4.3.5 SUBPROGRAM Types .................. 29
  180.  
  181.            5. Maps and Lists ........................................... 30
  182.                5.1 PROC Map ............................................ 30
  183.                5.2 CSeg Map ............................................ 31
  184.                5.3 Typed CONST DSeg Map ................................ 31
  185.                5.4 Global VAR DSeg Map ................................. 32
  186.                5.5 Donor Unit List ..................................... 32
  187.                5.6 Source File List .................................... 33
  188.                5.7 DEBUG Trace Table ................................... 34
  189.  
  190.            6. Code, Data, Fix-Up Info .................................. 35
  191.                6.1 Object CSegs ........................................ 35
  192.                6.2 CONST DSegs ......................................... 35
  193.                6.3 Fix-Up Data Table ................................... 36
  194.  
  195.            7. Supplied Program ......................................... 37
  196.  
  197.                7.1 TPU6 ................................................ 37
  198.                    7.1.1 UNIT TPU6AMS .................................. 37
  199.                    7.1.2 UNIT TPU6EQU .................................. 38
  200.                    7.1.3 UNIT TPU6UTL .................................. 38
  201.                    7.1.4 UNIT TPU6RPT .................................. 38
  202.                    7.1.5 UNIT TPU6UNA .................................. 38
  203.  
  204.                7.2 Modifications ....................................... 39
  205.  
  206.                7.3 Notes on Program Logic .............................. 39
  207.                    7.3.1 Formatting the Dictionary ..................... 39
  208.                    7.3.2 The Disassembler .............................. 41
  209.  
  210.            8. Unit Libraries ........................................... 43
  211.                8.1 Library Structure ................................... 43
  212.  
  213.            9. Application Notes ........................................ 44
  214.  
  215.            10. Acknowledgements ........................................ 45
  216.  
  217.            11. References .............................................. 46
  218.  
  219.            INDEX ....................................................... 47
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.                                        - iv -
  229.  
  230.  
  231.  
  232.                            Inside TURBO Pascal 6.0 Units              
  233.        ----------------------------------------------------------------------
  234.  
  235.        INTRODUCTION
  236.  
  237.  
  238.        This document  is  the  outcome  of  an  inquiry  conducted  into  the
  239.        structure and  content of  Borland Turbo  Pascal  (Version  6.0)  Unit
  240.        files.   The original  purpose of the inquiry was to provide a body of
  241.        theory enabling  Cross-Reference programs  to  resolve  references  to
  242.        symbols defined  in .TPU  files where qualification was not explicitly
  243.        provided.   As is  so often the case, one thing led to another and the
  244.        scope of  the inquiry  was expanded dramatically.  While this document
  245.        should not be regarded as definitive, the author feels that the entire
  246.        Turbo Pascal  User community might gain from the information extracted
  247.        from these files at the cost of so much time and effort.
  248.  
  249.        The  material   contained   herein   represents   the   findings   and
  250.        interpretations of  the author.    A  great  deal  of  guess-work  was
  251.        required and  no assurances are given as to the accuracy of either the
  252.        findings of fact or the inferences contained herein which are the sole
  253.        work-product of the author.  In particular, the author had access only
  254.        to materials  or information  that any  normal  Borland  customer  has
  255.        access to.   Further,  no Borland  source-codes were  available as the
  256.        Library Routine source is not licensed to the author.  In short, there
  257.        was nothing irregular about how these findings were achieved.
  258.  
  259.        The material  contained herein  is placed in the public domain free of
  260.        copyright for  use of  the general public at its own risk.  The author
  261.        assumes no  liability for  any damages  arising from  the use  of this
  262.        material by  others.   If you make use of this information and you get
  263.        burned, TOUGH!   The  author accepts no obligation to correct any such
  264.        errors as  may exist  in the  supplied programs  or in the findings of
  265.        fact or  opinion contained  herein.   On the other hand, this is not a
  266.        "complete" work in that a great many questions remain open, especially
  267.        as regards fine details.  (The author is not highly-qualified in Intel
  268.        80xxx Assembly  Language and  several open  questions  might  best  be
  269.        addressed by persons competent in this area.)  The author welcomes the
  270.        input of  interested readers  who might be able to "flesh-out" some of
  271.        these open questions with "hard" answers.
  272.  
  273.  
  274.        1. GROSS FILE STRUCTURE
  275.  
  276.  
  277.        A Turbo  Pascal Unit  file consists  of an array of bytes that is some
  278.        exact multiple  of sixteen  (16).   "Signature" information allows the
  279.        compiler to  verify that  the .TPU  file was compiled with the correct
  280.        compiler version  and to  verify that the file is of the correct size.
  281.        The fine  structure of the file will be addressed in later sections at
  282.        ever increasing levels of detail.
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.        ----------------------------------------------------------------------
  292.        Rev: April 16, 1991                                             Page 5
  293.  
  294.  
  295.  
  296.                            Inside TURBO Pascal 6.0 Units              
  297.        ----------------------------------------------------------------------
  298.  
  299.        Graphically, the  file may be regarded as having the following general
  300.        layout:
  301.  
  302.              +-------------------+
  303.              | Unit Header       |        Main Index to Unit File
  304.              |-------------------|
  305.              | Dictionaries:     |
  306.              |   a) Interface    |
  307.              |   b) Debug      * |        For Local Symbol Access
  308.              |-------------------|
  309.              | PROC Map          |
  310.              |-------------------|
  311.              | CSeg Map        * |        May be Empty
  312.              |-------------------|
  313.              | CONST DSeg Map  * |        May be Empty
  314.              |-------------------|
  315.              | VAR DSeg Map    * |        May be Empty
  316.              |-------------------|
  317.              | Donor Units     * |        May be Empty
  318.              |-------------------|
  319.              | Source Files      |
  320.              |-------------------|
  321.              | Trace Table     * |        May be Empty
  322.              |-------------------|
  323.              | CODE Segment(s) * |        May be Empty
  324.              |-------------------|
  325.              | DATA Segment(s) * |        May be Empty
  326.              |-------------------|
  327.              | FIX-UP Data     * |        May be Empty
  328.              +-------------------+
  329.  
  330.  
  331.        1.1 USER UNITS
  332.  
  333.  
  334.        Units prepared by the compiler available to ordinary users have a very
  335.        straight-forward appearance  and content.   There may even be a little
  336.        "wasted" space  that might  be removed  if the  compiler were  just  a
  337.        little cleverer.  The SYSTEM.TPU file is quite another thing however.
  338.  
  339.        The SYSTEM.TPU  file (found  in TURBO.TPL)  is extraordinary  in  that
  340.        great pains  seem to  have been  taken to  compact it.    Further,  it
  341.        contains a  great many  types of  entries that  just don't  seem to be
  342.        achievable by  ordinary users  and I suspect that much (if not all) of
  343.        it was "hand-coded" in Assembler Language.
  344.  
  345.        In the  following sections, the details of these optimizations will be
  346.        explained  in  the  context  of  the  structural  element  then  under
  347.        discussion.
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.        ----------------------------------------------------------------------
  356.        Rev: April 16, 1991                                             Page 6
  357.  
  358.  
  359.  
  360.                            Inside TURBO Pascal 6.0 Units              
  361.        ----------------------------------------------------------------------
  362.  
  363.        2. LOCATORS
  364.  
  365.  
  366.        The data  in these  files has  need of  structure and  organization to
  367.        support efficient access by the various programs such as the compiler,
  368.        the linker  and the  debugger.   This organization is built on a solid
  369.        foundation of locators employed in the unit's data structures.
  370.  
  371.  
  372.  
  373.        2.1 LOCAL LINKS
  374.  
  375.  
  376.        Local Links  (LL's) are  items of type WORD (2 bytes) which contain an
  377.        offset which  is relative to the origin of the unit file itself.  This
  378.        implies that  a unit must be somewhat less than 64K bytes in size.  If
  379.        the .TPU  file is  loaded into  the heap,  then an  LL can  be used to
  380.        locate any  byte in  the segment  beginning with the load point of the
  381.        file.
  382.  
  383.  
  384.  
  385.        2.2 GLOBAL LINKS
  386.  
  387.  
  388.        Global Links  (LG's) are used to locate type descriptors and to locate
  389.        allocation data  for variables  with the  ABSOLUTE attribute which may
  390.        reside in  other Units  (i.e., units  external to  the present  unit).
  391.        LG's are  structured items  consisting of two (2) words.  The first of
  392.        these is  an LL  that is  relative to  the origin  of  the  (possibly)
  393.        external unit.  It locates either a Type Descriptor or the stub of the
  394.        Dictionary entry  which establishes  storage allocation.   The  second
  395.        word is  an LL which locates the stub of the unit entry in the current
  396.        unit dictionary  for the  (possibly) external  unit.   This dictionary
  397.        entry provides  the name  of the  unit that  contains the  item the LG
  398.        points to.
  399.  
  400.        This provides  a handy  mechanism for  locating type  descriptors  and
  401.        allocation information  which  may  be  defined  in  other  separately
  402.        compiled units.
  403.  
  404.  
  405.  
  406.        2.3 TABLE OFFSETS
  407.  
  408.  
  409.        Finally, various  data-structures within  a .TPU file are organized as
  410.        arrays of fixed-length records or as lists of variable-length records.
  411.        Efficient access  to such  records is  achieved by  means  of  offsets
  412.        rather than subscripts (an addressing technique denied Pascal).  These
  413.        offsets are  relative to  the  origin  of  the  array  or  list  being
  414.        referenced rather than the origin of the unit.
  415.  
  416.  
  417.  
  418.  
  419.        ----------------------------------------------------------------------
  420.        Rev: April 16, 1991                                             Page 7
  421.  
  422.  
  423.  
  424.                            Inside TURBO Pascal 6.0 Units              
  425.        ----------------------------------------------------------------------
  426.  
  427.        2.4 BASIC RELATIONSHIPS
  428.  
  429.  
  430.           +-------------+                            +----------------------+
  431.           |    Unit     |                            | INTERFACE Dictionary |
  432.           |   Header    |                            |                      |
  433.           +-------------+                            | Public and Private   |
  434.                  |                                   | Names, Nested Hash   |
  435.                  |   LL    +----------------+  LL's  | Tables, INLINE code, |
  436.                  |-------->| INTERFACE Hash |------->| Type Descriptors.    |
  437.                  |         +----------------+        +----------------------+
  438.                  |                                        (LL's ^ & LG's)
  439.                  |                                   +----------------------+
  440.                  |   LL    +----------------+  LL's  |   DEBUG Dictionary   |
  441.                  |-------->|   DEBUG Hash   |------->| IMPLEMENTATION and   |
  442.                  |         +----------------+        | nested scope names,  |
  443.                  |                                  ?| stored for DEBUG.    |
  444.                  |   LL    +----------------+        | Same structure as in |
  445.                  |-------->| PROC Map Table |        | INTERFACE.  Linked   |
  446.                  |         +----------------+        | to INTERFACE part by |
  447.                  |   LL    +----------------+        | LL's.  BUILT ONLY IF |
  448.                  |-------->| CSeg Map Table |?       | LOCAL SYMBOLS ARE    |
  449.                  |         +----------------+        | ENABLED AT COMPILE.  |
  450.                  |   LL    +----------------+        +----------------------+
  451.                  |-------->| DSeg Map CONST |?
  452.                  |         +----------------+
  453.                  |   LL    +----------------+
  454.                  |-------->| DSeg Map VAR's |?
  455.                  |         +----------------+             IMPORTANT NOTES
  456.                  |   LL    +----------------+         ----------------------
  457.                  |-------->| Donor Unit List|?        Some of the structures
  458.                  |         +----------------+         shown in this figure
  459.                  |   LL    +------------------+       are built only if they
  460.                  |-------->| Source File List |       are needed.  These are
  461.                  |         +------------------+       marked by a "?" next
  462.                  |   LL    +------------------+       to the box.
  463.                  |-------->| Debug Step Ctls  |?
  464.                  |         +------------------+       If the DEBUG Dictionary
  465.                  |   **    +---------------+          is missing, its LL
  466.                  |-------->| CODE Segments |?         leads directly to the
  467.                  |         +---------------+          INTERFACE Dictionary.
  468.                  |   **    +-----------------+        ----------------------
  469.                  |-------->| CONST DATA Segs |?
  470.                  |         +-----------------+
  471.                  |   **    +----------------+
  472.                  +-------->| Fix-Up Lists   |?
  473.                            +----------------+
  474.  
  475.  
  476.  
  477.        This figure  illustrates the role of the Unit Header in tying together
  478.        the various  data structures  in the  Unit.  The type of link is shown
  479.        next to a flow-line by "LL", "LG" or "**".  "LL" and "LG" are explicit
  480.        pointers while  "**" shows  a locator  whose value  is computed  using
  481.        other data in the Unit Header and that no explicit pointer exists.
  482.  
  483.        ----------------------------------------------------------------------
  484.        Rev: April 16, 1991                                             Page 8
  485.  
  486.  
  487.  
  488.                            Inside TURBO Pascal 6.0 Units              
  489.        ----------------------------------------------------------------------
  490.  
  491.  
  492.         +----(from hash tables,other Dictionary Entries)
  493.         |
  494.         |    +------------------------------------------------+
  495.         |    | Header Part | Stub Part -- many formats        |
  496.         +--->| - - - - - - | - - - +------------------------- |
  497.              |             | data, | Some stubs have embedded | Dictionary
  498.              | Name, Class | links | Type Descriptors         |   Entry
  499.              | and link to | (see  |     +------------------- |
  500.              | entries who | below)|     | INLINE Declarative |
  501.              | have same   |   *   |     | code bytes for a   |
  502.              | hash        |   |   |     | "macro" type PROC  |
  503.              +-----------------|------------------------------+
  504.                     +----------+
  505.                     |
  506.                     | FAR pntr   +----------------------------+
  507.                     |----------->| Absolute Memory Locations  |
  508.                     |            +----------------------------+
  509.                     |            +-----------------------------+
  510.                     |   LG's     | Type Descriptors and stubs  |
  511.                     |----------->| of Dictionary Entries used  |
  512.                     |            | for absolute equivalences   |
  513.                     |            +-----------------------------+
  514.                     |            +---------------------------------+
  515.                     |   LL's     | Nested Scope Hash Tables        |
  516.                     |----------->| Parent Scope Dictionary Entries |
  517.                     |            | Record Fields                   |
  518.                     |            | Object Fields/Methods           |
  519.                     |            +---------------------------------+
  520.                     |            +----------------------+
  521.                     | Offsets    | CONST DSeg Map Table |
  522.                     +----------->| PROC Map Table       |
  523.                                  | VAR DSeg Map Table   |
  524.                                  +----------------------+
  525.  
  526.  
  527.  
  528.        This figure illustrates the many types of entities that associate with
  529.        Dictionary Entries and particularly with their Stub Parts.  Not all of
  530.        the links shown occur in a single Stub format, but all of the links in
  531.        the figure can and do exist in selected cases.  The purpose here is to
  532.        show the  flexibility of  the system  of links in associating required
  533.        data with the Dictionary Entry and its identifying symbol.
  534.  
  535.        While it may not be apparent from the figure, the dictionary structure
  536.        as a whole may be viewed as a cyclic directed graph which is rooted in
  537.        the DEBUG  Hash Table.  The recursive properties exhibited by the node
  538.        relationships permit direct support of the scope rules of Turbo Pascal
  539.        with simplicity and elegance.  As one might expect, the representation
  540.        of the  required information  lends itself to efficient use of storage
  541.        since the  representations are compact and there is very little in the
  542.        way of  redundancy.  The small amount of redundancy that does exist is
  543.        apparently aimed at speeding access to certain structures by the Turbo
  544.        components (compiler, linker and debugger).
  545.  
  546.  
  547.        ----------------------------------------------------------------------
  548.        Rev: April 16, 1991                                             Page 9
  549.  
  550.  
  551.  
  552.                            Inside TURBO Pascal 6.0 Units              
  553.        ----------------------------------------------------------------------
  554.  
  555.  
  556.         +----(implied links, explicit LG's from other structures)
  557.         |
  558.         |    +---------------------------------------------+
  559.         |    | Flags and codes, allocation widths for data |  Type
  560.         +--->| and VMT's, subrange constraints, formal     |  Descriptor
  561.              | parameter descriptors, implicit associated  |  Contents &
  562.              | type descriptors, LL's, LG's and Offsets.   |  Linkages
  563.              +---------------------------------------------+
  564.                     |
  565.                     |
  566.                     |    LG's       +------------------+
  567.                     |-------------->| Type Descriptors |
  568.                     |               +------------------+
  569.                     |
  570.                     |               +-------------------------------+
  571.                     |    LL's       | Method Dictionary Entries     |
  572.                     |-------------->| Nested Scope Hash Tables      |
  573.                     |               | Nested Scope Field Chains     |
  574.                     |               | Parent Scope Dictionary Entry |
  575.                     |               +-------------------------------+
  576.                     |
  577.                     |  Offsets      +----------------------------------+
  578.                     +-------------->| VMT pointers in Object Instances |
  579.                                     | CONST DSeg Map Table Entries     |
  580.                                     +----------------------------------+
  581.  
  582.  
  583.        This figure illustrates the relationships between Type Descriptors and
  584.        other structures in the dictionary.  Not all the links shown can exist
  585.        with a single Type Descriptor since there are several variant forms of
  586.        these descriptors  (depending on  base type) but in combination, these
  587.        linkages are  feasible.   In addition to links, a great amount of data
  588.        is stored  which is peculiar to a given type declaration.  Descriptors
  589.        can be  -- and are -- shared.  Indeed, they were designed with that in
  590.        mind.   Once a  named type is declared, all entities that reference it
  591.        are linked to it in some way (usually by an LG).
  592.  
  593.        Almost every  form of  type descriptor is found in the SYSTEM unit and
  594.        this fact is used to advantage.  When un-typed constants are declared,
  595.        a built-in  type descriptor  is referenced  (via an LG) which provides
  596.        necessary information for maintenance of orderly dictionary structure.
  597.        When a  named-type is declared, it is almost always decomposed into an
  598.        expression based on the built-in types of Turbo Pascal which are found
  599.        in the SYSTEM unit with the aid of an LG.
  600.  
  601.        The semantics  underlying the  idea of  the  Unit  mandate  this  very
  602.        approach since  program modules  of any class which make references to
  603.        units for  definitions use  the definitions as implemented by the unit
  604.        which contains them.  Re-defining the unit or any of its defined types
  605.        leads to  a natural  requirement to  re-compile those  program modules
  606.        which rely  on the  unit for  definitions.   The impact is fundamental
  607.        since the  storage representation  of a  unit-defined named  type  can
  608.        change in quite radical ways.
  609.  
  610.  
  611.        ----------------------------------------------------------------------
  612.        Rev: April 16, 1991                                            Page 10
  613.  
  614.  
  615.  
  616.                            Inside TURBO Pascal 6.0 Units              
  617.        ----------------------------------------------------------------------
  618.  
  619.  
  620.  
  621.        3. UNIT HEADER
  622.  
  623.  
  624.        The Unit  Header comprises  the first  64 bytes  of the .TPU file.  It
  625.        contains LL's  that effectively  locate all other sections of the .TPU
  626.        file plus  statistics  that  enable  a  little  cross-checking  to  be
  627.        performed.   Some parts  of the  Unit Header appear to be reserved for
  628.        future use  since no  unit examined  by this author has ever contained
  629.        non-zero data in these apparently reserved fields.
  630.  
  631.  
  632.  
  633.        3.1 DESCRIPTION
  634.  
  635.  
  636.        The Unit Header provides a high-level locator table whereby each major
  637.        structure in the unit file can be addressed.  The following provides a
  638.        Pascal-like explanation  of the  layout  of  the  header  followed  by
  639.        further narrative  discussion of the contents of the individual fields
  640.        in the Unit Header.
  641.  
  642.              Type HdrAry = Array[0..3] of Char; LL = Word;
  643.  
  644.              UnitHeader = Record
  645.  
  646.               UHEYE : HdrAry;   { +00 : = 'TPU9'                      }
  647.               UHxxx : HdrAry;   { +04 : = $00000000                   }
  648.               UHUDH : LL;       { +08 : to Dictionary Head-This Unit  }
  649.               UGIHT : LL;       { +0A : to Hash Table (INTERFACE)     }
  650.               UHPMT : LL;       { +0C : to PROC Map                   }
  651.               UHCMT : LL;       { +0E : to CSeg Map                   }
  652.               UHTMT : LL;       { +10 : to DSeg Map-Typed CONST's     }
  653.               UHDMT : LL;       { +12 : to DSeg Map-GLOBAL Variables  }
  654.               UHxxy : LL;       { +14 : Purpose Unknown               }
  655.               UHLDU : LL;       { +16 : to Donor Unit List            }
  656.               UHLSF : LL;       { +18 : to Source file List           }
  657.               UHDBT : LL;       { +1A : to Debug Trace Step Controls  }
  658.               UHENC : LL;       { +1C : to end non-code part of Unit  }
  659.               UHZCS : Word;     { +1E : Size of CSEGs (aggregate)     }
  660.               UHZDT : Word;     { +20 : Size of Typed Constant Data   }
  661.               UHZFA : Word;     { +22 : Fix-Up Bytes (CSegs)          }
  662.               UHZFT : Word;     { +24 : Fix-Up Bytes (Typed CONST's)  }
  663.               UHZFV : Word;     { +26 : Size of GLOBAL VAR Data       }
  664.               UHDHT : LL;       { +28 : to Hash Table (DEBUG)         }
  665.               UHSOV : Word;     { +2A : Overlay Involved if non-zero  }
  666.               UHPad : Array[0..9]
  667.                       of Word;  { +2C : Reserved for Future Expansion }
  668.  
  669.              End; { UnitHeader }
  670.  
  671.          UHEYE   contains the  characters "TPU9"  in that  order.   This is
  672.                  clear evidence that this unit was compiled by Turbo Pascal
  673.                  Version 6.0.
  674.  
  675.        ----------------------------------------------------------------------
  676.        Rev: April 16, 1991                                            Page 11
  677.  
  678.  
  679.  
  680.                            Inside TURBO Pascal 6.0 Units              
  681.        ----------------------------------------------------------------------
  682.  
  683.          UHxxx   is apparently reserved and contains binary zeros.
  684.  
  685.          UHUDH   contains an  LL (WORD)  which  points  to  the  Dictionary
  686.                  Header in which the name of this unit is found.
  687.  
  688.          UHIHT   contains an LL (WORD) which points to a Hash table that is
  689.                  the root of the Interface Dictionary graph.
  690.  
  691.          UHPMT   contains an  LL (WORD)  which points  to the  PROC Map for
  692.                  this unit.   The  PROC Map  contains  an  entry  for  each
  693.                  Procedure or  Function declared  in the  unit (except  for
  694.                  INLINE types),  plus an  entry for the Unit Initialization
  695.                  section.   The length  of  the  PROC  Map  (in  bytes)  is
  696.                  determined by subtracting this UHPMT from UHCMT.
  697.  
  698.          UHCMT   contains an  LL (WORD)  which points  to  the  CSeg  (CODE
  699.                  Segment) Map  for this  unit.   The CSeg  Map contains  an
  700.                  entry for  each CODE Segment produced by the compiler plus
  701.                  an entry  for each  of the  CODE Segments included via the
  702.                  {$L filename.OBJ}  compiler directive.  The length of this
  703.                  Map (in  bytes) is  obtained  by  subtracting  UNCMT  from
  704.                  UHTMT.   The result may be zero in which case the CSeg Map
  705.                  is empty.
  706.  
  707.          UHTMT   contains an  LL (WORD)  which points  to  the  DSeg  (DATA
  708.                  Segment) Map  that maps  the initializing  data for  Typed
  709.                  CONST items  plus  templates  for  VMT's  (Virtual  Method
  710.                  Tables) that  are associated  with  OBJECTS  which  employ
  711.                  Virtual Methods.   The  length of  this Map  (in bytes) is
  712.                  obtained by  subtracting UHTMT from UHDMT.  The result may
  713.                  be zero in which case this DSeg Map is empty.
  714.  
  715.          UHDMT   contains an  LL (WORD)  which points  to  the  DSeg  (DATA
  716.                  Segment) Map  that contains  the specifications  for  DSeg
  717.                  storage required  by VARiables whose scope is GLOBAL.  The
  718.                  length of  this Map  (in bytes) is obtained by subtracting
  719.                  UHDMT from  UHxxy.   The result  may be zero in which case
  720.                  this DSeg Map is empty.
  721.  
  722.          UHxxy   Purpose of  this word is unknown.  No non-zero values have
  723.                  ever been observed here.  (May be for TP-Windows?)
  724.  
  725.          UHLDU   contains an  LL (WORD)  which points  to a  table of units
  726.                  which contribute  either CODE or DATA Segments to the .EXE
  727.                  file for  a program  using this  Unit.  This is called the
  728.                  "Donor Unit  Table".   The length of this table (in bytes)
  729.                  is obtained by subtracting UHLDU from the word UHLSF.  The
  730.                  result may be zero in which case this table is empty.
  731.  
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739.        ----------------------------------------------------------------------
  740.        Rev: April 16, 1991                                            Page 12
  741.  
  742.  
  743.  
  744.                            Inside TURBO Pascal 6.0 Units              
  745.        ----------------------------------------------------------------------
  746.  
  747.          UHLSF   contains an  LL (WORD)  which points to a list of "source"
  748.                  files.   These are  the files  whose CODE or DATA Segments
  749.                  are included  in this  Unit by the compiler.  Examples are
  750.                  the Pascal Source for the Unit itself, plus the .OBJ files
  751.                  included via  the {$L  filename.OBJ}  compiler  directive.
  752.                  The length  of  this  table  (in  bytes)  is  obtained  by
  753.                  subtracting UHLSF  from the word UHDBT.  The result may be
  754.                  zero in which case this table is empty.
  755.  
  756.          UHDBT   contains an  LL (WORD)  which points to a Trace Table used
  757.                  by the  DEBUGGER for  "stepping"  through  a  Function  or
  758.                  Procedure contained  in this  Unit.   The length  of  this
  759.                  table (in bytes) is obtained by subtracting UHDBT from the
  760.                  word UHENC.   The  result may  be zero  in which case this
  761.                  table is empty.
  762.  
  763.          UHENC   contains an  LL (WORD) which points to the first free byte
  764.                  which follows  the Trace  Table (if  any).  It serves as a
  765.                  delimiter for  determining the  size of  the Trace  Table.
  766.                  This LL  (when rounded up to the next integral multiple of
  767.                  16) serves to locate the start of the code/data segments.
  768.  
  769.          UHZCS   is a  WORD that  contains the total byte count of all CODE
  770.                  Segments compiled into this Unit.
  771.  
  772.          UHZDT   is a  WORD that contains the total byte count of all Typed
  773.                  CONST and VMT DATA Segments compiled into this unit.
  774.  
  775.          UHZFA   is a WORD that contains the total byte count of the Fix-Up
  776.                  Data Table for this unit for CODE (CSegs).
  777.  
  778.          UHZFT   is a WORD that contains the total byte count of the Fix-Up
  779.                  Data Table for Typed CONST's.  This usually implies that a
  780.                  VMT is getting its pointers relocated.
  781.  
  782.          UHZFV   is a WORD that contains the total byte count of all GLOBAL
  783.                  VAR DATA Segments compiled into this unit.
  784.  
  785.          UHDHT   contains an  LL (WORD)  which points to a Hash Table which
  786.                  is the  root of the DEBUGGER Dictionary.  If Local Symbols
  787.                  were generated  by the compiler (directive {$L+}) then ALL
  788.                  symbols declared  in the  unit can  be accessed  from this
  789.                  Hash Table.   If Local Symbols were suppressed there is no
  790.                  such Dictionary  and the  LL stored  here  points  to  the
  791.                  INTERFACE Dictionary.
  792.  
  793.          UHSOV   Purpose of  this word is unknown.  It has been observed to
  794.                  be non-zero  when overlay  directives are  used.   So  far
  795.                  however, this  hasn't enabled  me to  come up  with a good
  796.                  guess as to just what the observed values actually mean.
  797.  
  798.          UHPad   begins a  series of  ten (10)  words that  are  apparently
  799.                  reserved for future use.  Nothing but zeros have ever been
  800.                  seen here by this author.
  801.  
  802.  
  803.        ----------------------------------------------------------------------
  804.        Rev: April 16, 1991                                            Page 13
  805.  
  806.  
  807.  
  808.                            Inside TURBO Pascal 6.0 Units              
  809.        ----------------------------------------------------------------------
  810.  
  811.  
  812.        3.2 UNIT SIZE
  813.  
  814.  
  815.        An independent  check on  the size of the .TPU file is available using
  816.        information contained  in the Unit Header.  This is also important for
  817.        .TPL (Unit Library) organization.  To compute the file :size, refer to
  818.        the five  (5) words  -- UHENC,  UHZCS, UHZDT, UHZFA, and UHZFT.  Round
  819.        the contents  of each of these words to the lowest multiple of 16 that
  820.        is greater  than or  equal to the content of that word.  Then form the
  821.        sum of the rounded words.  This is the .TPU file size in bytes.
  822.  
  823.  
  824.        4. SYMBOL DICTIONARIES
  825.  
  826.  
  827.        This area contains all available documentation of declared symbols and
  828.        procedure blocks  defined within  the unit.    Depending  on  compiler
  829.        options in  effect when  the unit  was  compiled,  this  section  will
  830.        contain at  a minimum,  the INTERFACE  declarations, and at a maximum,
  831.        ALL declarations.   The information stored in the dictionary is highly
  832.        dependent on  the context  of the  symbol declared.   We defer further
  833.        explanation to the appropriate section which follows.
  834.  
  835.  
  836.        4.1 ORGANIZATION
  837.  
  838.  
  839.        A dictionary  is organized  with a  Hash Table  as its root.  The hash
  840.        table is used to provide rapid access to identifiers.
  841.  
  842.        A dictionary  may be thought of as a directed graph.  Each subgraph is
  843.        rooted in  a hash  table.   There may be a great many hash tables in a
  844.        given unit  and their number depends on unit complexity as well as the
  845.        options chosen when the unit was compiled.  Use of the {$L+} directive
  846.        produces the  largest dictionaries.   The hash tables are explained in
  847.        detail a few sections further on.
  848.  
  849.        Hash tables  point to  Dictionary Headers.   When  two or more symbols
  850.        produce the  same hash  function result, a collision is said to occur.
  851.        Collisions  are  resolved  by  the  time-honored  method  of  chaining
  852.        together the  Dictionary Headers of those symbols having the same hash
  853.        function result.   Dictionary supersetting is accomplished using these
  854.        chains.
  855.  
  856.  
  857.        4.2 INTERFACE DICTIONARY
  858.  
  859.  
  860.        The INTERFACE  dictionary  contains  all  symbols  and  the  necessary
  861.        explanatory data  for the  INTERFACE section  of a  Unit.  Symbols get
  862.        added to  the  Unit  using  increasing  storage  addresses  until  the
  863.        IMPLEMENTATION section is encountered.
  864.  
  865.  
  866.  
  867.        ----------------------------------------------------------------------
  868.        Rev: April 16, 1991                                            Page 14
  869.  
  870.  
  871.  
  872.                            Inside TURBO Pascal 6.0 Units              
  873.        ----------------------------------------------------------------------
  874.  
  875.        4.3 DEBUG DICTIONARY
  876.  
  877.  
  878.        The Debug  dictionary (if  present) is  a superset  of  the  INTERFACE
  879.        dictionary.   It is  used by  the Turbo  Debugger to  support its many
  880.        features when  tracing through a unit.  If present, this dictionary is
  881.        rooted in  its  own  hash  table.    The  hash  table  is  effectively
  882.        initialized when  the  IMPLEMENTATION  keyword  is  processed  by  the
  883.        compiler.   This takes  the form  (initially) of an unmodified copy of
  884.        the INTERFACE  hash table,  to which  symbols are  added in  the usual
  885.        fashion.   Thus, the  hash chains constructed or extended at this time
  886.        lead naturally to the INTERFACE chains and this is how the superset is
  887.        effectively implemented.
  888.  
  889.  
  890.        4.4 DICTIONARY ELEMENTS
  891.  
  892.  
  893.        The dictionary contains four major elements.  These are:  hash tables,
  894.        Dictionary Headers,  Dictionary  Stubs  and  Type  Descriptors.    The
  895.        distinction between  Dictionary Headers  and Stubs  might appear to be
  896.        rather arbitrary.   They  might just as easily be regarded as a single
  897.        element (such  as symbol  entry).   However, the case for the separate
  898.        entity approach  is strong since Stubs are DIRECTLY addressed via LG's
  899.        and --  more to  the point -- ONLY by LG's.  Thus, it seems reasonable
  900.        that this  is a  separate and  very important structure -- at least in
  901.        the minds of the architects at Borland.
  902.  
  903.  
  904.        4.4.1 HASH TABLES
  905.  
  906.  
  907.        As has  been intimated,  Hash Tables  are  the  glue  that  binds  the
  908.        dictionary entries  together and  gives the  dictionary  its  "shape".
  909.        They effectively  implement the  scope rules of the language and speed
  910.        access to essential information.
  911.  
  912.        Each Hash table begins with a 2-byte size descriptor.  This descriptor
  913.        contains the  number of bytes in the table proper (less 2).  Thus, the
  914.        descriptor directly  points to the last bucket in the hash table.  For
  915.        a hash  table of  128 bytes,  the size  descriptor contains  126.  The
  916.        first bucket in the table immediately follows the size descriptor.
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.        ----------------------------------------------------------------------
  932.        Rev: April 16, 1991                                            Page 15
  933.  
  934.  
  935.  
  936.                            Inside TURBO Pascal 6.0 Units              
  937.        ----------------------------------------------------------------------
  938.  
  939.        4.4.1.1 SIZE
  940.  
  941.  
  942.        So far,  three different  hash table  sizes have  been observed.   The
  943.        INTERFACE and  DEBUG hash tables are usually 128 bytes (64 entries) in
  944.        size plus  2 bytes  of size  description, but the SYSTEM.TPU unit is a
  945.        special case,  containing only  16 entries.   Hash tables which anchor
  946.        subgraphs whose  scope is  relatively local  usually contain  four (4)
  947.        entries (8 bytes).
  948.  
  949.        Graphically, a Hash Table with four slots has the following layout:
  950.  
  951.              +--------------------+
  952.              |       0006h        |      Size Descriptor
  953.              |--------------------|
  954.              |       slot 0       |      an LL or zero
  955.              |--------------------|
  956.              |       slot 1       |      an LL or zero
  957.              |--------------------|
  958.              |       slot 2       |      an LL or zero
  959.              |--------------------|
  960.              |       slot 3       |      an LL or zero
  961.              +--------------------+
  962.  
  963.        It should  be noted  that the Size Descriptor furnishes an upper bound
  964.        for the  hash function  itself.  Thus, it seems possible that a single
  965.        hash function is used for all hash tables and that its result is ANDed
  966.        with the  Size Descriptor  to get the final result.  Because the sizes
  967.        are chosen  as they  are (powers of 2) this is feasible.  Note that in
  968.        the above  example, 6  = 2 * (n - 1) where n = 4 {slot count}.  All of
  969.        the hash tables observed so far have this property.
  970.  
  971.        One final  note on this subject.  Given these properties, "Folding" of
  972.        sparse hash  tables is  a rather  trivial exercise  so long as the new
  973.        hash table also contains a number of slots that is a power of 2.  This
  974.        point is  intriguing when  one recalls  that the SYSTEM.TPU hash table
  975.        has only 16 slots rather than the usual 64.
  976.  
  977.  
  978.  
  979.        4.4.1.2 SCOPE
  980.  
  981.  
  982.        The INTERFACE  and Debug  dictionary hash  tables are  Global in Scope
  983.        even though the symbols accessed directly via either hash table may be
  984.        private.   On the  other hand,  other hash  tables are purely local in
  985.        scope.   For example,  the fields declared within a record are reached
  986.        via a small local hash table, as are the arguments and local variables
  987.        declared within  procedures and  functions.   Even  OBJECTS  use  this
  988.        technique to provide access to Methods and Object Fields.
  989.  
  990.        Access to  such local  scope fields/methods  requires use of qualified
  991.        names which  ensures conformity  to Pascal scope rules.  The method is
  992.        truly simple and elegant.
  993.  
  994.  
  995.        ----------------------------------------------------------------------
  996.        Rev: April 16, 1991                                            Page 16
  997.  
  998.  
  999.  
  1000.                            Inside TURBO Pascal 6.0 Units              
  1001.        ----------------------------------------------------------------------
  1002.  
  1003.  
  1004.        4.4.1.3 SPECIAL CASES
  1005.  
  1006.  
  1007.        The SYSTEM.TPU  Unit is  a special case.  Its INTERFACE hash table has
  1008.        apparently been  "hand-tuned" for  small size  and  it  contains  only
  1009.        sixteen (16)  entries.   In addition,  the Debug  hash table is absent
  1010.        since there  is no  local symbol  generation in this unit.  Therefore,
  1011.        the Debug hash table does not exist as a separate entity, its function
  1012.        being served  by the  INTERFACE hash  table.  The pointer to the Debug
  1013.        hash table  (in the  Unit Header) has the same value as the pointer to
  1014.        the INTERFACE hash table.
  1015.  
  1016.  
  1017.        4.4.2 DICTIONARY HEADERS
  1018.  
  1019.  
  1020.        This is  the structure  that anchors  all  information  known  by  the
  1021.        compiler about any symbol.  The format is as follows:
  1022.  
  1023.          +00:    An LL  which points  to the  next (previous) symbol in the
  1024.                  same unit which had the same hash function value.
  1025.  
  1026.          +02:    A character  that defines  the category the symbol belongs
  1027.                  to and  defines the  format of  the Dictionary  Stub which
  1028.                  follows the  Dictionary Header.  If the symbol is declared
  1029.                  in the  component list  of the "private" part of an Object
  1030.                  declaration, then this character is modified by adding $80
  1031.                  to  its  ordinal  value.    Thus,  an  ordinary  Function,
  1032.                  Procedure or  Method is  of category  "S" while  a private
  1033.                  Method is of category Chr(Ord('S')+$80).
  1034.  
  1035.          +03:    A String  (in the  Pascal sense)  of  variable  size  that
  1036.                  contains the  text of  the symbol  (in UPPER-CASE  letters
  1037.                  only).   The SizeOf  function is  not  defined  for  these
  1038.                  strings since they are truncated to match the symbol size.
  1039.                  The "value"  of the  SizeOf function  can be determined by
  1040.                  adding  1  to  the  first  byte  in  the  string.    Thus,
  1041.                  Ord(Symbol[0])+1 is  the expression  that defines the Size
  1042.                  of the  symbol string.  Turbo Pascal defines a symbol as a
  1043.                  string of  relatively arbitrary size, the most significant
  1044.                  63 characters  of which  will be stored in the dictionary.
  1045.                  Thus, we  conclude that  the maximum size of such a string
  1046.                  is 64 bytes.
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.        ----------------------------------------------------------------------
  1060.        Rev: April 16, 1991                                            Page 17
  1061.  
  1062.  
  1063.  
  1064.                            Inside TURBO Pascal 6.0 Units              
  1065.        ----------------------------------------------------------------------
  1066.  
  1067.  
  1068.        4.4.3 DICTIONARY STUBS
  1069.  
  1070.  
  1071.        Dictionary Stubs immediately follow their respective headers and their
  1072.        format is  determined by  the category  character  in  the  Dictionary
  1073.        Header.   The function  of the  stub is  to organize  the  information
  1074.        appropriate to  the symbol and provide a means of accessing additional
  1075.        information such as type descriptors, constant values, parameter lists
  1076.        and nested  scopes.   The format  of each  Stub is  presented  in  the
  1077.        following sub-sections.
  1078.  
  1079.  
  1080.        4.4.3.1 LABEL DECLARATIVES ("O")
  1081.  
  1082.  
  1083.        This Stub consists of a WORD whose function is (as yet) unknown.
  1084.  
  1085.  
  1086.        4.4.3.2 UN-TYPED CONSTANTS ("P")
  1087.  
  1088.  
  1089.        This Stub consists of (2) two fields:
  1090.  
  1091.          +00:    An LG  which points  to  a  Type  Descriptor  (usually  in
  1092.                  SYSTEM.TPU).     This  establishes   the  minimum  storage
  1093.                  requirement for  the constant.   The  rules vary  with the
  1094.                  type, but  the size  of the  constant  data  field  (which
  1095.                  follows) is defined using the Type Descriptor(s).
  1096.  
  1097.          +04:    The value  of the constant.  For ordinal types, this value
  1098.                  is stored as a LONGINT (size=4 bytes).  For Floating-Point
  1099.                  types, the  size is  implicit in  the type  itself.    For
  1100.                  String types,  the size  is determined  from the length of
  1101.                  the string  which is  stored in  the initial  byte of  the
  1102.                  constant.
  1103.  
  1104.  
  1105.        4.4.3.3 NAMED TYPES ("Q")
  1106.  
  1107.  
  1108.        This Stub  consists of  an  LG  (4-bytes)  that  points  to  the  Type
  1109.        Descriptor for this symbol.
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.        ----------------------------------------------------------------------
  1124.        Rev: April 16, 1991                                            Page 18
  1125.  
  1126.  
  1127.  
  1128.                            Inside TURBO Pascal 6.0 Units              
  1129.        ----------------------------------------------------------------------
  1130.  
  1131.        4.4.3.4 VARIABLES, FIELDS, TYPED CONS ("R")
  1132.  
  1133.  
  1134.        This Stub contains information required to allocate and describe these
  1135.        types of entities.  The format and content is as follows:
  1136.  
  1137.          +00:    A one-byte flag that precisely identifies the class of the
  1138.                  item being described.  The known values and their apparent
  1139.                  meanings follow:
  1140.  
  1141.                  $00 -> Global Variables (Allocated in DS);
  1142.                  $01 -> Typed Constants (Allocated in DS);
  1143.                  $02 -> Procedure LOCAL Variables on STACK;
  1144.                  $03 -> Variables at Absolute Addresses;
  1145.                  $06 -> ADDRESS Arguments allocated on STACK; (This is now
  1146.                         used only for SELF in Method calls;)
  1147.                  $08 -> Fields sub-allocated in RECORDS and OBJECTS, plus
  1148.                         METHODS declared for OBJECTS.
  1149.                  $10 -> Variable Equivalenced to another via the
  1150.                         Absolute Clause;
  1151.                  $22 -> Arguments whose VALUEs are passed on the stack;
  1152.                  $26 -> Arguments whose ADDRESSes are passed on the stack.
  1153.  
  1154.          +01     Two words  whose content vary with the codes above.  Their
  1155.                  content is explained following the last item in the stub.
  1156.  
  1157.          +05:    An LG  that locates  the proper  Type Descriptor  for this
  1158.                  symbol.
  1159.  
  1160.        When the  code byte  at +00 is $02,$06,$22 or $26 (arguments), the two
  1161.        words at +01 are used as follows:
  1162.  
  1163.          +01     Word -- Offset relative to either DS or BP.
  1164.          +03     Word -- LL to Dict Header of Parent Scope, or zero.
  1165.  
  1166.        If the code byte is $00 or $01 (VAR's or typed CONSTs), then we have:
  1167.  
  1168.          +01     Word -- Offset relative to allocation area origin;
  1169.          +03     Word -- Offset to entry in VAR/CONST Map for item
  1170.                          allocation;
  1171.  
  1172.        When the code byte is $03 (Absolute Address Variable), then we have:
  1173.  
  1174.          +01     DWord -- FAR Pointer to Absolute Memory Address.
  1175.  
  1176.        When the  code byte  is $08  (Record/Object Fields/Methods),  then  we
  1177.        have:
  1178.  
  1179.          +01     Word -- Allocation Offset within Record/Object;
  1180.          +03     Word -- LL to next Field/Method.
  1181.  
  1182.        When the code byte is $10 (Absolute Equivalences), then we have:
  1183.  
  1184.          +01     DWord -- LG to STUB of variable/parameter declaration that
  1185.                           actually establishes the allocation;
  1186.  
  1187.        ----------------------------------------------------------------------
  1188.        Rev: April 16, 1991                                            Page 19
  1189.  
  1190.  
  1191.  
  1192.                            Inside TURBO Pascal 6.0 Units              
  1193.        ----------------------------------------------------------------------
  1194.  
  1195.  
  1196.        4.4.3.5 SUBPROGRAMS & METHODS ("S")
  1197.  
  1198.  
  1199.        Subprograms (PROC's),  especially since  Object Methods are supported,
  1200.        have a rather involved stub.  Its format is as follows:
  1201.  
  1202.          +00:    A byte  that contains  bit-switches that  seem to describe
  1203.                  the Call  Model and  imply the  size of  this stub.  These
  1204.                  switches determine what kind of code (if any) is generated
  1205.                  when the  PROC is  referenced.  The observed values are as
  1206.                  follows:
  1207.  
  1208.                  xxxxx001 -> PROC uses FAR Call Model;
  1209.                  xxxx0010 -> PROC uses INLINE Model (no Call);
  1210.                  xxxx0100 -> PROC uses INTERRUPT Model (no Call);
  1211.                  xxxx100x -> PROC has EXTERNAL attribute;
  1212.                  xxx1xxxx -> PROC uses METHOD Call Model;
  1213.                  x011xxxx -> PROC is a CONSTRUCTOR Method;
  1214.                  x101xxxx -> PROC is a DESTRUCTOR Method;
  1215.                  1xxxxxxx -> PROC has ASSEMBLER directive.
  1216.  
  1217.          +01     A byte whose function is not yet known. (TP Windows?)
  1218.  
  1219.          +02:    A Word  whose interpretation  depends on whether or not we
  1220.                  have an  INLINE Declarative  Subprogram.   If this  is  an
  1221.                  INLINE Declarative Subprogram, then this word contains the
  1222.                  byte-count of  the INLINE  code text  at the  end of  this
  1223.                  stub.   Otherwise, this word is the offset within the PROC
  1224.                  Map that locates the object code for this Subprogram.
  1225.  
  1226.          +04:    A Word  that contains  an LL  which locates the containing
  1227.                  scope in the dictionary, or zero if none.
  1228.  
  1229.          +06:    A Word  that contains  an LL  which locates the local Hash
  1230.                  Table for  this scope.  A local hash table provides access
  1231.                  to all  formal parameters of the Subprogram as well as all
  1232.                  Symbols whose  declarations are local to the scope of this
  1233.                  Subprogram.
  1234.  
  1235.          +08:    A Word that is zero unless the symbol is a Virtual Method.
  1236.                  In this  case, then  the content  is the offset within the
  1237.                  VMT for  the owning  object that  defines  where  the  FAR
  1238.                  POINTER to this Virtual Method is stored.
  1239.  
  1240.          +0A:    A complete  Type-Descriptor  for  this  Subprogram.    The
  1241.                  length is  variable and  depends upon the number of Formal
  1242.                  Parameters declared in the header.  (See 4.4.4.3.5).
  1243.  
  1244.          +??:    If  this   Symbol   represents   an   INLINE   Declarative
  1245.                  Subprogram, then  the object-code  text begins  here.  The
  1246.                  byte-count of  the text  occurs at  offset 0002h  in  this
  1247.                  stub.
  1248.  
  1249.  
  1250.  
  1251.        ----------------------------------------------------------------------
  1252.        Rev: April 16, 1991                                            Page 20
  1253.  
  1254.  
  1255.  
  1256.                            Inside TURBO Pascal 6.0 Units              
  1257.        ----------------------------------------------------------------------
  1258.  
  1259.        4.4.3.6 TURBO STD PROCEDURES ("T")
  1260.  
  1261.  
  1262.        This Stub consists of two bytes, the first of which is unique for each
  1263.        procedure and  increments by  4.   I have  found nothing in the SYSTEM
  1264.        unit (which  is where  this entry  appears) that  this seems  directly
  1265.        related to.  The second byte is always zero.
  1266.  
  1267.  
  1268.        4.4.3.7 TURBO STD FUNCTIONS ("U")
  1269.  
  1270.  
  1271.        This Stub consists of two bytes, the first of which is unique for each
  1272.        function and increments by 4.  I have found nothing in the SYSTEM unit
  1273.        (which is  where this  entry appears) that this seems directly related
  1274.        to.   I wouldn't  be surprised if this byte were an index into a TURBO
  1275.        compiler table that points to specialized parse tables/action routines
  1276.        for handling these functions and their non-standard parameter lists.
  1277.  
  1278.        The second byte seems to be a flag having the values $00, $40 and $C0.
  1279.        I strongly  suspect that  the flag  $C0 marks  exactly those functions
  1280.        which may  be evaluated at compile-time.  The meaning behind the other
  1281.        values is not known to me.
  1282.  
  1283.  
  1284.        4.4.3.8 TURBO STD "NEW" ROUTINE ("V")
  1285.  
  1286.  
  1287.        This Stub consists of a WORD whose function is (as yet) unknown.  This
  1288.        is the  only Standard  Turbo routine that can behave as a procedure as
  1289.        well as a function (returning a pointer value).
  1290.  
  1291.  
  1292.        4.4.3.9 TURBO STD PORT ARRAYS ("W")
  1293.  
  1294.  
  1295.        This Stub  consists of  a byte whose value is 0 for byte arrays, and 1
  1296.        for word arrays.
  1297.  
  1298.  
  1299.        4.4.3.10 TURBO STD EXTERNAL VARIABLES ("X")
  1300.  
  1301.  
  1302.        This Stub  consists of  an  LG  (4-bytes)  that  points  to  the  Type
  1303.        Descriptor for this symbol.
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.        ----------------------------------------------------------------------
  1316.        Rev: April 16, 1991                                            Page 21
  1317.  
  1318.  
  1319.  
  1320.                            Inside TURBO Pascal 6.0 Units              
  1321.        ----------------------------------------------------------------------
  1322.  
  1323.        4.4.3.11 UNITS ("Y")
  1324.  
  1325.  
  1326.        Unit Stubs have the following content:
  1327.  
  1328.          +00:    A Word  whose apparently  reserved for use by the Compiler
  1329.                  or Linker.
  1330.  
  1331.          +02:    A Word that seems to contain some kind of "signature" used
  1332.                  to detect  inconsistent Unit Versions.  Borland calls this
  1333.                  a "unit  version number,  which is basically a checksum of
  1334.                  the interface  part."   I have  seen a thread in CIS which
  1335.                  says that it is a CRC value.  Food for thought?
  1336.  
  1337.          +04:    A Word  that contains  an LL  which locates  the Successor
  1338.                  Unit in  the "Uses"  list.   In fact,  the "Uses" lists of
  1339.                  both the INTERFACE and IMPLEMENTATION sections of the Unit
  1340.                  are merged  by this  Word into  a single list.  A value of
  1341.                  zero is used to indicate no successor.
  1342.  
  1343.          +06:    A Word  that contains  an LL which locates the Predecessor
  1344.                  Unit in  the "Uses" list.  For the SYSTEM unit entry, this
  1345.                  value is  always zero to indicate no predecessor.  For the
  1346.                  Unit being compiled, this LL locates the final Unit in the
  1347.                  combined "Uses" list.
  1348.  
  1349.        In effect,  the two  LL's at  offsets 0004 and 0006 organize the units
  1350.        into both  forward and backward linked chains.  The entry for the unit
  1351.        being compiled  is effectively  the head  of both  the forward and the
  1352.        backward chains.  The final unit in the merged "Uses" list is the tail
  1353.        of the  forward chain, and the SYSTEM unit is the tail of the backward
  1354.        chain.
  1355.  
  1356.  
  1357.        4.4.4 TYPE DESCRIPTORS
  1358.  
  1359.  
  1360.        Type Descriptors  store much  of the semantic information that applies
  1361.        to the  symbols declared  in the  unit.  Implementation details can be
  1362.        managed using  high-level abstractions  and these  abstractions can be
  1363.        shared.
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.        ----------------------------------------------------------------------
  1380.        Rev: April 16, 1991                                            Page 22
  1381.  
  1382.  
  1383.  
  1384.                            Inside TURBO Pascal 6.0 Units              
  1385.        ----------------------------------------------------------------------
  1386.  
  1387.        4.4.4.1 SCOPE
  1388.  
  1389.  
  1390.        Type Descriptor  sharing can  occur across  the boundaries  which  are
  1391.        implicit in  unit modules.   Thus,  a type  defined in one unit may be
  1392.        "imported" by  some other  module.  Also, the pre-defined Pascal Types
  1393.        (plus the  Turbo Pascal extensions) are defined in the SYSTEM.TPU unit
  1394.        and there  needs to  be a  means of  "importing" such Type Descriptors
  1395.        during compilation.  This is precisely the objective of the LG locator
  1396.        which was  described in  section 2.2  (above).   Type Descriptors  are
  1397.        NEVER copied between units.  The binding always occurs by reference at
  1398.        compile time  and this helps support the technique of modifying a unit
  1399.        and compiling  it to a .TPU file, then re-compiling all units/programs
  1400.        that "USE" it.
  1401.  
  1402.        Type Descriptors  have many  roles so  their format  varies.   We have
  1403.        divided these  structures into  two parts:   The PREFIX Part (which is
  1404.        always present  and) whose  format is  fairly constant  and the SUFFIX
  1405.        Part whose  content and format depends on the attributes that are part
  1406.        of the type definition.
  1407.  
  1408.  
  1409.        4.4.4.2 PREFIX PART
  1410.  
  1411.  
  1412.        The Prefix  Part of  every Type  Descriptor consists of six (6) bytes.
  1413.        The usage  is consistent for all types observed by this author and the
  1414.        format is as follows:
  1415.  
  1416.          +00:    A Byte  that identifies  the format  of the  Suffix  part.
  1417.                  This is essentially based on several high-level categories
  1418.                  which the Suffix Parts support directly.  The observed set
  1419.                  of values is as follows:
  1420.  
  1421.                  00h -> an un-typed entity;
  1422.                  01h -> an ARRAY type;
  1423.                  02h -> a RECORD type;
  1424.                  03h -> an OBJECT type;
  1425.                  04h -> a FILE type (other than TEXT);
  1426.                  05h -> a TEXT File type;
  1427.                  06h -> a SUBPROGRAM type;
  1428.                  07h -> a SET type;
  1429.                  08h -> a POINTER type;
  1430.                  09h -> a STRING type;
  1431.                  0Ah -> an 8087 Floating-Point type;
  1432.                  0Bh -> a REAL type;
  1433.                  0Ch -> a Fixed-Point ordinal type;
  1434.                  0Dh -> a BOOLEAN type;
  1435.                  0Eh -> a CHAR type;
  1436.                  0Fh -> an Enumerated ordinal type.
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.        ----------------------------------------------------------------------
  1444.        Rev: April 16, 1991                                            Page 23
  1445.  
  1446.  
  1447.  
  1448.                            Inside TURBO Pascal 6.0 Units              
  1449.        ----------------------------------------------------------------------
  1450.  
  1451.          +01:    A Byte  used as a modifier.  Since the above scheme is too
  1452.                  general for  machine-dependent  details  such  as  storage
  1453.                  width  and  sign  control,  this  modifier  byte  supplies
  1454.                  additional data.   The author has identified several cases
  1455.                  in which  this information is vital but has not spent very
  1456.                  much time  on the  subject.  The chief areas of importance
  1457.                  seem to  be in  the 8087  Floating-Point  types,  and  the
  1458.                  Fixed-Point ordinal  types.   The semantics  seem to be as
  1459.                  follows:
  1460.  
  1461.                  0A 00 -> The type "SINGLE"
  1462.                  0A 02 -> The type "EXTENDED"
  1463.                  0A 04 -> The type "DOUBLE"
  1464.                  0A 06 -> The type "COMP"
  1465.  
  1466.                  0C 00 -> an un-named BYTE integer
  1467.                  0C 01 -> The type "SHORTINT"
  1468.                  0C 02 -> The type "BYTE"
  1469.                  0C 04 -> an un-named WORD integer
  1470.                  0C 05 -> The type "INTEGER"
  1471.                  0C 06 -> The type "WORD"
  1472.                  0C 0C -> an un-named double-word integer
  1473.                  0C 0D -> The type "LONGINT"
  1474.  
  1475.                  One important  feature of  the above semantics is the fact
  1476.                  that an un-typed CONST declaration refers to the above two
  1477.                  bytes  to  determine  the  storage  space  needed  in  the
  1478.                  dictionary for  the data  value of the constant.  This can
  1479.                  be a  little involved  however as the constant may contain
  1480.                  its own  length descriptor (as in a string)  in which case
  1481.                  it may  be sufficient  to  identify  the  high-level  type
  1482.                  category without any modifier byte.
  1483.  
  1484.          +02:    A Word  that contains  the number of bytes of storage that
  1485.                  are required  to contain  an object/entity  of this  type.
  1486.                  For types  that represent variable-length objects/entities
  1487.                  such as  strings, this  word may define the value returned
  1488.                  by the SIZEOF function as applied to the type.
  1489.  
  1490.          +04     A Word that is zero unless the descriptor is for an Object
  1491.                  Method.   In this  case, the  content  is  an  LL  to  the
  1492.                  Dictionary Header of the SUCCEEDING Method for the Object,
  1493.                  in order of declaration, or zero if none.
  1494.  
  1495.  
  1496.        4.4.4.3 SUFFIX PARTS
  1497.  
  1498.  
  1499.        Suffix Parts further refine the implementation details of the type and
  1500.        also provide  subrange constraints  where appropriate.   In some cases
  1501.        the Suffix  part is  empty since  all semantic  data for  the type  is
  1502.        contained in the Prefix part.
  1503.  
  1504.  
  1505.  
  1506.  
  1507.        ----------------------------------------------------------------------
  1508.        Rev: April 16, 1991                                            Page 24
  1509.  
  1510.  
  1511.  
  1512.                            Inside TURBO Pascal 6.0 Units              
  1513.        ----------------------------------------------------------------------
  1514.  
  1515.        4.4.4.3.1 UN-TYPED
  1516.  
  1517.  
  1518.        This Suffix Part is empty.  Nothing is known about an un-typed entity.
  1519.  
  1520.  
  1521.        4.4.4.3.2 STRUCTURED TYPES
  1522.  
  1523.  
  1524.        The structured  types represent  aggregates of  lower-level types.  We
  1525.        include ARRAY,  RECORD, OBJECT,  FILE, TEXT,  SET, POINTER  and STRING
  1526.        types in this category.
  1527.  
  1528.  
  1529.        4.4.4.3.2.1 ARRAY TYPES
  1530.  
  1531.  
  1532.        The Suffix  Part of  the ARRAY type is so constructed as to be able to
  1533.        support recursive  or nested  definition of arrays.  The suffix format
  1534.        is as follows:
  1535.  
  1536.          +00:    An LG that locates the Type Descriptor for the "base-type"
  1537.                  of the  array.   This is  the type  of  the  entity  being
  1538.                  arrayed (which may itself be an array).
  1539.  
  1540.          +04:    An LG  that locates  the Type  Descriptor  for  the  array
  1541.                  bounds which is a constrained ordinal type or subrange.
  1542.  
  1543.  
  1544.        4.4.4.3.2.2 RECORD TYPES
  1545.  
  1546.  
  1547.        RECORD types  have nested  scopes.   The Suffix  part provides  a base
  1548.        structure by  which to  locate the  fields local  to the  scope of the
  1549.        Record type itself.  The format is as follows:
  1550.  
  1551.          +00:    A Word containing an LL which locates the local Hash Table
  1552.                  that provides access to the fields in the nested scope.
  1553.  
  1554.          +02:    A Word  containing an  LL  which  locates  the  Dictionary
  1555.                  Header of  the initial  field in  the nested  scope.  This
  1556.                  supports a  "left-to-right" traversal  of the  fields in a
  1557.                  record.
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.        ----------------------------------------------------------------------
  1572.        Rev: April 16, 1991                                            Page 25
  1573.  
  1574.  
  1575.  
  1576.                            Inside TURBO Pascal 6.0 Units              
  1577.        ----------------------------------------------------------------------
  1578.  
  1579.        4.4.4.3.2.3 OBJECT TYPES
  1580.  
  1581.  
  1582.        OBJECT types also have nested scopes.  The Suffix part provides a base
  1583.        structure by which to locate the fields and METHODS local to the scope
  1584.        of  the  OBJECT  type  itself.    In  addition,  inheritance  and  VMT
  1585.        particulars are stored.  The format is as follows:
  1586.  
  1587.          +00:    A Word containing an LL which locates the local Hash Table
  1588.                  that provides  access to  the fields  and METHODS local to
  1589.                  the nested scope.
  1590.  
  1591.          +02:    A Word  containing an  LL  which  locates  the  Dictionary
  1592.                  Header of the initial field or METHOD in the nested scope.
  1593.                  This supports  a "left-to-right"  traversal of  the fields
  1594.                  and METHODS in an OBJECT.
  1595.  
  1596.          +04:    An LG  which locates  the Type  Descriptor of  the  Parent
  1597.                  Object.  This field is zero if there is no such Parent.
  1598.  
  1599.          +08:    A Word  which contains  the size  in bytes  of the VMT for
  1600.                  this Object.   This field is zero if the object employs no
  1601.                  Virtual Methods, Constructors or Destructors.
  1602.  
  1603.          +0A:    A Word which contains the offset within the CONST DSeg Map
  1604.                  that locates  the VMT  skeleton or template segment.  This
  1605.                  field equals  FFFFh  if  the  object  employs  no  Virtual
  1606.                  Methods, Constructors or Destructors.
  1607.  
  1608.          +0C:    A Word which contains the offset within an Object instance
  1609.                  where the NEAR POINTER to the VMT for the object is stored
  1610.                  (within the DATA SEGMENT).  This field equals FFFFh if the
  1611.                  object  employs   no  Virtual   Methods,  Constructors  or
  1612.                  Destructors.
  1613.  
  1614.          +0E:    A Word  which contains  an LL which locates the Dictionary
  1615.                  Header for the name of the OBJECT itself.
  1616.  
  1617.          +10:    A Word (not yet understood) containing $FFFF.
  1618.  
  1619.          +12:    Three Words (not yet understood) containing zeroes.
  1620.  
  1621.  
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.  
  1630.  
  1631.  
  1632.  
  1633.  
  1634.  
  1635.        ----------------------------------------------------------------------
  1636.        Rev: April 16, 1991                                            Page 26
  1637.  
  1638.  
  1639.  
  1640.                            Inside TURBO Pascal 6.0 Units              
  1641.        ----------------------------------------------------------------------
  1642.  
  1643.        4.4.4.3.2.4 FILE (NON-TEXT) TYPES
  1644.  
  1645.  
  1646.        This Suffix  consists of an LG that locates the Type Descriptor of the
  1647.        base type  of the  file.  Note that the Type Descriptor may be that of
  1648.        an un-typed entity (for un-typed files).
  1649.  
  1650.  
  1651.        4.4.4.3.2.5 TEXT FILE TYPES
  1652.  
  1653.  
  1654.        This Suffix  consists of an LG that locates the Type Descriptor of the
  1655.        base type of the file -- in this case SYSTEM.CHAR.
  1656.  
  1657.  
  1658.        4.4.4.3.2.6 SET TYPES
  1659.  
  1660.  
  1661.        This Suffix  consists of  an LG  that locates the base-type of the set
  1662.        itself.    Pascal  limits  such  entities  to  simple  ordinals  whose
  1663.        cardinality is limited to 256.
  1664.  
  1665.  
  1666.        4.4.4.3.2.7 POINTER TYPES
  1667.  
  1668.  
  1669.        This Suffix consists of an LG that locates the base-type of the entity
  1670.        pointed at.
  1671.  
  1672.  
  1673.        4.4.4.3.2.8 STRING TYPES
  1674.  
  1675.  
  1676.        This is a special case of an ARRAY type.  The format is as follows:
  1677.  
  1678.          +00:    An LG to the Type Descriptor SYSTEM.CHAR which is the base
  1679.                  type of all Turbo Pascal Strings.
  1680.  
  1681.          +04:    An  LG  to  the  Type  Descriptor  for  the  array  bounds
  1682.                  constraints for the string.  When the unconstrained STRING
  1683.                  type is  used, this points to SYSTEM.BYTE which is defined
  1684.                  as a subrange 0..255.
  1685.  
  1686.  
  1687.        4.4.4.3.3 FLOATING-POINT TYPES
  1688.  
  1689.  
  1690.        The Suffix  part for  all Floating-Point  types is  EMPTY.   All  data
  1691.        needed to  specify these  approximate number types is contained in the
  1692.        Prefix part.   The  Types included  in this  class are SINGLE, DOUBLE,
  1693.        EXTENDED, COMP and REAL.
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.        ----------------------------------------------------------------------
  1700.        Rev: April 16, 1991                                            Page 27
  1701.  
  1702.  
  1703.  
  1704.                            Inside TURBO Pascal 6.0 Units              
  1705.        ----------------------------------------------------------------------
  1706.  
  1707.        4.4.4.3.4 ORDINAL TYPES
  1708.  
  1709.  
  1710.        The Ordinal  Types consist  of the  various "integer"  types plus  the
  1711.        BOOLEAN, CHAR and Enumerated types.
  1712.  
  1713.  
  1714.        4.4.4.3.4.1 "INTEGERS"
  1715.  
  1716.  
  1717.        These types  include BYTE, SMALLINT, WORD, INTEGER and LONGINT.  Their
  1718.        Suffix parts are identical in format:
  1719.  
  1720.          +00:    A double-word  containing the  LOWER bound of the subrange
  1721.                  constraint on the type;
  1722.  
  1723.          +04:    A double-word  containing the  UPPER bound of the subrange
  1724.                  constraint on the type;
  1725.  
  1726.          +08:    An LG  that locates  the Type  Descriptor of  the  largest
  1727.                  upward compatible  type.  This is the Type Descriptor that
  1728.                  is used  to control  the width  of an un-typed constant in
  1729.                  the dictionary  stub.  For the "integer" types, this is an
  1730.                  LG to SYSTEM.LONGINT.
  1731.  
  1732.  
  1733.        4.4.4.3.4.2 BOOLEANS
  1734.  
  1735.  
  1736.        This type Suffix has the following format:
  1737.  
  1738.          +00:    A double-word  containing the  LOWER bound of the subrange
  1739.                  constraint on the type;
  1740.  
  1741.          +04:    A double-word  containing the  UPPER bound of the subrange
  1742.                  constraint on the type;
  1743.  
  1744.          +08:    An LG  that locates  the Type  Descriptor  SYSTEM.BOOLEAN.
  1745.                  There is no "upward compatible" type.
  1746.  
  1747.  
  1748.        4.4.4.3.4.3 CHARS
  1749.  
  1750.  
  1751.        This type Suffix has the following format:
  1752.  
  1753.          +00:    A double-word  containing the  LOWER bound of the subrange
  1754.                  constraint on the type;
  1755.  
  1756.          +04:    A double-word  containing the  UPPER bound of the subrange
  1757.                  constraint on the type;
  1758.  
  1759.          +08:    An LG that locates the Type Descriptor SYSTEM.CHAR.  There
  1760.                  is no "upward compatible" type.
  1761.  
  1762.  
  1763.        ----------------------------------------------------------------------
  1764.        Rev: April 16, 1991                                            Page 28
  1765.  
  1766.  
  1767.  
  1768.                            Inside TURBO Pascal 6.0 Units              
  1769.        ----------------------------------------------------------------------
  1770.  
  1771.  
  1772.        4.4.4.3.4.4 ENUMERATIONS
  1773.  
  1774.  
  1775.        This type Suffix is unusual and has the following format:
  1776.  
  1777.          +00:    A double-word  containing the  LOWER bound of the subrange
  1778.                  constraint on the type;
  1779.  
  1780.          +04:    A double-word  containing the  UPPER bound of the subrange
  1781.                  constraint on the type;
  1782.  
  1783.          +08:    An  LG  that  locates  the  Prefix  of  the  current  Type
  1784.                  Descriptor.  There is no upward compatible type.
  1785.  
  1786.        What follows  is a full-fledged SET Type Descriptor whose base type is
  1787.        the Type Descriptor of the Enumerated Type itself.  The author has not
  1788.        yet discovered the reason for this.
  1789.  
  1790.        At least  one case  has been  observed where  a set type descriptor is
  1791.        followed by  a word  containing zero  but I  know of  no  explanation.
  1792.        Could this be a (shudder) BUG in Turbo?
  1793.  
  1794.  
  1795.        4.4.4.3.5 SUBPROGRAM TYPES
  1796.  
  1797.  
  1798.        The length of this Suffix is variable.  The format is as follows:
  1799.  
  1800.          +00:    An LG  that locates  the Type  Descriptor of  the FUNCTION
  1801.                  result returned  by the Subprogram.  This field is zero if
  1802.                  the Subprogram is a PROCEDURE.
  1803.  
  1804.          +04:    A Word  that contains  the number  of Formal Parameters in
  1805.                  the Function/Procedure  header.   If non-zero,  then  this
  1806.                  word is  followed by the parameter list itself as a simple
  1807.                  array of parameter descriptors.
  1808.  
  1809.                  The format of a parameter descriptor is as follows:
  1810.  
  1811.                  0000: An LG that locates the Type Descriptor of the   
  1812.                        corresponding parameter;
  1813.  
  1814.                  0004: A Byte that identifies the parameter passing    
  1815.                        mechanism used for this entry as follows:
  1816.  
  1817.                        02h -> VALUE of parameter is passed on STACK,   
  1818.                        06h -> ADDRESS of parameter is passed on STACK.
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825.  
  1826.  
  1827.        ----------------------------------------------------------------------
  1828.        Rev: April 16, 1991                                            Page 29
  1829.  
  1830.  
  1831.  
  1832.                            Inside TURBO Pascal 6.0 Units              
  1833.        ----------------------------------------------------------------------
  1834.  
  1835.  
  1836.        5. MAPS AND LISTS
  1837.  
  1838.  
  1839.        The "MAPS  and LISTS"  are not part of the symbol dictionary.  Rather,
  1840.        these structures provide access to the Code and Data Segments produced
  1841.        by the  compiler or  included via  the {$L  name.OBJ} directive.   The
  1842.        format and  purpose (as  understood by  this author)  of each of these
  1843.        tables is explained in the following sections.
  1844.  
  1845.  
  1846.        5.1 PROC MAP
  1847.  
  1848.  
  1849.        The PROC  Map provides a means of associating the various Function and
  1850.        Procedure declarations with the Code Segments.  There is some evidence
  1851.        that the  Compiler produces  CODE (and  DATA) Segments for EACH of the
  1852.        Subprograms defined  in the  Unit as  well as  for the  un-named  Unit
  1853.        Initialization code block.  There is also evidence that EXTERNAL PROCs
  1854.        must be  assembled separately  in order  to exploit  fully  the  Turbo
  1855.        "Smart Linker" since Turbo Pascal places some significant restrictions
  1856.        on  EXTERNAL  routines  in  the  area  of  Segment  Names  and  Types.
  1857.        Specifically, only  code segments named "CODE" and data segments named
  1858.        "DATA" or  "CONST" will  be used  by the  "Smart Linker" as sources of
  1859.        code and  data for  inclusion in a Turbo Pascal .EXE file.  (Turbo 6.0
  1860.        relaxed Name  constraints but only one code segment per .OBJ remains a
  1861.        limitation).
  1862.  
  1863.        The first  entry in  the PROC  Map is reserved for Unit Initialization
  1864.        block.   If there  is no Unit Initialization block, this entry will be
  1865.        filled with  $FF.  In addition, each and every PROC in the Unit has an
  1866.        entry in this table.
  1867.  
  1868.        If an  EXTERNAL routine  is included, then ALL PUBLIC PROC definitions
  1869.        in that  routine must  be declared  in the  Unit Source  Code with the
  1870.        EXTERNAL attribute.
  1871.  
  1872.        The size  of the  PROC Map  Table (in  Bytes) is  implied in  the Unit
  1873.        Header by the LL's that occur at offsets +0C and +0E.
  1874.  
  1875.        The Format of a single PROC Map Entry is as follows:
  1876.  
  1877.          +00:    A Word presumably reserved as a work area; always zero.
  1878.  
  1879.          +02:    A Word presumably reserved as a work area; always zero.
  1880.  
  1881.          +04:    A Word  that contains an offset within the CSeg Map.  This
  1882.                  is used to locate the code segment containing the PROC.
  1883.  
  1884.          +06:    A Word  that contains  an offset  within the  CODE Segment
  1885.                  that defines  the PROC  entry point  relative to  the load
  1886.                  point of the referenced CODE Segment.
  1887.  
  1888.  
  1889.  
  1890.  
  1891.        ----------------------------------------------------------------------
  1892.        Rev: April 16, 1991                                            Page 30
  1893.  
  1894.  
  1895.  
  1896.                            Inside TURBO Pascal 6.0 Units              
  1897.        ----------------------------------------------------------------------
  1898.  
  1899.        5.2 CSEG MAP
  1900.  
  1901.  
  1902.        The CSeg  Map provides  a convenient  descriptor table  for each  CODE
  1903.        Segment present  in the  Unit and serves to relate these segments with
  1904.        the Segment  Relocation Data  and the  Segment Trace  Table.  It seems
  1905.        reasonable to infer that the "Smart Linker" is able to include/exclude
  1906.        code/data at the SEGMENT level only.
  1907.  
  1908.        The CSeg  Map is  an array  of fixed-length records whose format is as
  1909.        follows:
  1910.  
  1911.          +00:    A Word apparently reserved for use by TURBO.
  1912.  
  1913.          +02:    A Word that contains the Segment Length (in bytes).
  1914.  
  1915.          +04:    A Word  that contains  the Length of the Fix-Up Data Table
  1916.                  for this Code Segment (in bytes).
  1917.  
  1918.          +06:    A Word  that contains  the offset of the Trace Table Entry
  1919.                  for this  Segment (if it was compiled with DEBUG Support).
  1920.                  If there  is no  Trace Table  for this  segment, then this
  1921.                  Word contains FFFFh.
  1922.  
  1923.  
  1924.        5.3 TYPED CONST DSEG MAP
  1925.  
  1926.  
  1927.        The CONST  DSeg Map  provides a  convenient descriptor  table for each
  1928.        DATA Segment  which was  spawned by the presence of Typed Constants or
  1929.        VMT's in the Pascal Code.  It serves to relate these segments with the
  1930.        Segment Fix-Up (relocation) Data and with the Code Segments that refer
  1931.        to these  DATA  elements.    One  entry  is  present  for  each  CONST
  1932.        declaration part containing typed constants and for each CONST segment
  1933.        linked from  an ".OBJ" file.  The CONST DSeg Map is an array of fixed-
  1934.        length records whose format is as follows:
  1935.  
  1936.          +00:    A Word apparently reserved for use by TURBO.
  1937.  
  1938.          +02:    A Word that contains the Segment Length (in bytes).
  1939.  
  1940.          +04:    A Word  that contains  the Length of the Fix-Up Data Table
  1941.                  for this DATA Segment (in bytes).
  1942.  
  1943.          +06:    A Word  that contains  an LL which locates the OBJECT that
  1944.                  owns this VMT template or zero if the segment is not a VMT
  1945.                  template.
  1946.  
  1947.        One can  determine the defining block for a Typed Constant declaration
  1948.        and our  program attempts  to do  just that.    A  by-product  of  the
  1949.        dictionary mapping  algorithm allows  the declaring  block to be found
  1950.        and its  qualified name  printed.   This information  is also  used to
  1951.        explain fix-up  data as  to its  source.   Results will  be incomplete
  1952.        unless a really comprehensive dictionary is present in the unit.
  1953.  
  1954.  
  1955.        ----------------------------------------------------------------------
  1956.        Rev: April 16, 1991                                            Page 31
  1957.  
  1958.  
  1959.  
  1960.                            Inside TURBO Pascal 6.0 Units              
  1961.        ----------------------------------------------------------------------
  1962.  
  1963.  
  1964.        5.4 GLOBAL VAR DSEG MAP
  1965.  
  1966.  
  1967.        The VAR  DSeg Map provides a convenient descriptor table for each DATA
  1968.        Segment present in the Unit.
  1969.  
  1970.        One entry  exists for  each CODE  segment which refers to GLOBAL VAR's
  1971.        allocated in  the DATA  Segment.   These references may be seen in the
  1972.        Fix-Up Data  Table.   Each EXTERNAL  CSeg having  a segment named DATA
  1973.        also spawns  an entry in this table.  Only the Code Segments that meet
  1974.        these criteria cause entries to be generated in the VAR Dseg Map.
  1975.  
  1976.        The VAR  DSeg Map  is an array of fixed-length records whose format is
  1977.        as follows:
  1978.  
  1979.          +00:    A Word apparently reserved for use by TURBO.
  1980.  
  1981.          +02:    A Word  that contains the Segment Length (in bytes).  This
  1982.                  may be zero, especially if the EXTERNAL routine contains a
  1983.                  DATA segment  whose sole purpose is to declare one or more
  1984.                  EXTRN symbols  that  are  defined  in  some  DATA  segment
  1985.                  external to the Assembly.
  1986.  
  1987.          +04:    A Word apparently reserved for use by TURBO.
  1988.  
  1989.          +06:    A Word apparently reserved for use by TURBO.
  1990.  
  1991.        One can determine the defining block for a Global VARiable declaration
  1992.        and our  program attempts  to do  just that.    A  by-product  of  the
  1993.        dictionary mapping  algorithm allows  the declaring  block to be found
  1994.        and its  qualified name  printed.   This information  is also  used to
  1995.        explain fix-up  data as  to its  source.   Results will  be incomplete
  1996.        unless a really comprehensive dictionary is present in the unit.  Such
  1997.        DSegs can  be referenced  by many  CSegs and  we only locate the first
  1998.        one.   This is  okay for  Pascal code but it's ambiguous for assembler
  1999.        since the names may be PUBLIC and referenced by more than one module.
  2000.  
  2001.  
  2002.        5.5 DONOR UNIT LIST
  2003.  
  2004.  
  2005.        This list contains an entry for each Unit (taken from the "USES" list)
  2006.        which MAY  contribute either CODE or DATA to the executable file.  Not
  2007.        all units do make such a contribution as some exist merely to define a
  2008.        collection of  Types, etc.  A Unit gets into this list if there exists
  2009.        a single Fix-Up Data Entry that references CODE or DATA in that Unit.
  2010.  
  2011.        The list  is comprised  of elements  whose SIZE  is variable and whose
  2012.        format is as follows:
  2013.  
  2014.          +00:    A WORD apparently reserved for use by TURBO.
  2015.  
  2016.          +02:    A variable-length String containing the unit name.
  2017.  
  2018.  
  2019.        ----------------------------------------------------------------------
  2020.        Rev: April 16, 1991                                            Page 32
  2021.  
  2022.  
  2023.  
  2024.                            Inside TURBO Pascal 6.0 Units              
  2025.        ----------------------------------------------------------------------
  2026.  
  2027.  
  2028.        5.6 SOURCE FILE LIST
  2029.  
  2030.  
  2031.        This list contains an entry for each "source" file used to compile the
  2032.        Unit.   This includes the Primary Pascal file, files containing Pascal
  2033.        code included  by means  of the  {$I filename.xxx} compiler directive,
  2034.        and .OBJ files included by the {$L filename.OBJ} compiler directive.
  2035.  
  2036.        The order  of entries  in this list is critical since it maps the CODE
  2037.        segments stored in the unit.  The order of the entries is as follows:
  2038.  
  2039.          1)      The Primary Pascal file;
  2040.  
  2041.          2)      All Included Pascal files;
  2042.  
  2043.          3)      All Included .OBJ files.
  2044.  
  2045.        Mapping of CSegs to files is done as follows:
  2046.  
  2047.          a)      Each .OBJ file contributes a SINGLE Code Segment (if any).
  2048.                  Note that this author has not observed an .OBJ module that
  2049.                  contains only  a DATA  Segment (but  that seems a distinct
  2050.                  possibility).
  2051.  
  2052.          b)      The Primary  Pascal file (augmented by all included Pascal
  2053.                  Files) contributes zero or more CODE Segments.
  2054.  
  2055.        Therefore, there  are at least as many CSeg entries as .OBJ files.  If
  2056.        more, then  the excess entries (those at the front of the list) belong
  2057.        to the Pascal files that make up the Pascal source for the unit.
  2058.  
  2059.        The format of an entry in this list is as follows:
  2060.  
  2061.          +00:    A flag byte that indicates the type of file represented;      
  2062.  
  2063.                  04h -> the Primary Pascal Source File,        
  2064.                  03h -> an Included Pascal Source File,        
  2065.                  05h -> an .OBJ file that contains a CODE segment.
  2066.  
  2067.          +01:    A Word apparently reserved for use by the Compiler/Linker.
  2068.  
  2069.          +03:    A Word  that is zero for .OBJ files and which contains the
  2070.                  file directory time-stamp for Pascal Files.
  2071.  
  2072.          +05:    A Word  that is zero for .OBJ files and which contains the
  2073.                  file directory date-stamp for Pascal Files.
  2074.  
  2075.          +07:    A  variable-sized   string  containing  the  filename  and
  2076.                  extension of the file used during compilation.
  2077.  
  2078.  
  2079.  
  2080.  
  2081.  
  2082.  
  2083.        ----------------------------------------------------------------------
  2084.        Rev: April 16, 1991                                            Page 33
  2085.  
  2086.  
  2087.  
  2088.                            Inside TURBO Pascal 6.0 Units              
  2089.        ----------------------------------------------------------------------
  2090.  
  2091.        5.7 DEBUG TRACE TABLE
  2092.  
  2093.  
  2094.        If Debug  support was  selected at  compile time, then all Pascal code
  2095.        which supports  Debugging produces  an entry in this table.  The table
  2096.        entries themselves are variable in size and have the following format:
  2097.  
  2098.          +00:    A Word  which contains  an LL  that locates  the Directory
  2099.                  Header of the Symbol (a PROC name) this entry represents.
  2100.  
  2101.          +02:    A Word  which contains  the offset (within the Source File
  2102.                  List) of  the entry that names the file that generated the
  2103.                  CSeg being traced.  This allows the file included by means
  2104.                  of the  {$I filename} directive to be identified for DEBUG
  2105.                  purposes, as well as code produced from the Primary File.
  2106.  
  2107.          +04:    A Word containing the number of bytes of data that precede
  2108.                  the BEGIN statement code in the segment.  For Pascal PROCS
  2109.                  these  bytes   consist  of   literal  constants,  un-typed
  2110.                  constants, and  other data  such as range-checking limits,
  2111.                  etc.
  2112.  
  2113.          +06:    A Word  containing the  Line Number of the BEGIN statement
  2114.                  for the PROC.
  2115.  
  2116.          +08:    A Word  containing the  number of  lines of Source Code to
  2117.                  Trace in this Segment.
  2118.  
  2119.          +0A:    An array  of bytes  whose size   is at least the number of
  2120.                  source code  lines in  the PROC.   Each  byte contains the
  2121.                  number of bytes of object code in the corresponding source
  2122.                  line.   This appears to be an array of SHORTINT since if a
  2123.                  "line" contains more than 127 bytes, then a single byte of
  2124.                  $80 precedes  the actual  byte count as a sort of "escape"
  2125.                  and the  next byte  records the  up to  255 bytes  for the
  2126.                  line.  This situation has not yet been fully explored.  We
  2127.                  do not  yet know  what happens  in the  event  a  line  is
  2128.                  credited with spawning more than 255 bytes of code.
  2129.  
  2130.  
  2131.  
  2132.  
  2133.  
  2134.  
  2135.  
  2136.  
  2137.  
  2138.  
  2139.  
  2140.  
  2141.  
  2142.  
  2143.  
  2144.  
  2145.  
  2146.  
  2147.        ----------------------------------------------------------------------
  2148.        Rev: April 16, 1991                                            Page 34
  2149.  
  2150.  
  2151.  
  2152.                            Inside TURBO Pascal 6.0 Units              
  2153.        ----------------------------------------------------------------------
  2154.  
  2155.        6. CODE, DATA, FIX-UP INFO
  2156.  
  2157.  
  2158.        This area  begins at the start of the next free PARAGRAPH.  This means
  2159.        that its  offset from  the beginning  of the  Unit ALWAYS  ends in the
  2160.        digit zero.
  2161.  
  2162.        This area  contains the  CODE segments,  CONST DATA  segments, and the
  2163.        Relocation (Fix-Up) Data required for linking.
  2164.  
  2165.  
  2166.        6.1 OBJECT CSEGS
  2167.  
  2168.  
  2169.        Each CODE  segment included  in the  unit appears here as specified by
  2170.        the CSeg  Map Table.  Depending on usage, these segments may appear in
  2171.        the executable file.  There are no filler bytes between segments.
  2172.  
  2173.  
  2174.        6.2 CONST DSEGS
  2175.  
  2176.  
  2177.        This section begins at the start of the first free PARAGRAPH following
  2178.        the end  of the  Object CSegs.   This  means that  its offset from the
  2179.        beginning of the Unit ALWAYS ends in the digit zero.
  2180.  
  2181.        A DATA  segment fragment  appears here  for each  CSeg that declares a
  2182.        typed constant,  and for  each OBJECT  which employs  Virtual Methods,
  2183.        Constructors or  Destructors.   There  are  no  filler  bytes  between
  2184.        segments.
  2185.  
  2186.        If local symbols were generated, there is always enough information to
  2187.        allow documenting the scope of the declaration as well as interpreting
  2188.        the data  in the display since the needed type declarations would also
  2189.        be available.  Our program merely identifies the defining block.
  2190.  
  2191.  
  2192.  
  2193.  
  2194.  
  2195.  
  2196.  
  2197.  
  2198.  
  2199.  
  2200.  
  2201.  
  2202.  
  2203.  
  2204.  
  2205.  
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.        ----------------------------------------------------------------------
  2212.        Rev: April 16, 1991                                            Page 35
  2213.  
  2214.  
  2215.  
  2216.                            Inside TURBO Pascal 6.0 Units              
  2217.        ----------------------------------------------------------------------
  2218.  
  2219.        6.3 FIX-UP DATA TABLE
  2220.  
  2221.  
  2222.        This table  begins at  the start of the first free PARAGRAPH following
  2223.        the end  of the  CONST DSegs.   This  means that  its offset  from the
  2224.        beginning of  the Unit  ALWAYS ends  in the digit zero.  There are two
  2225.        sections in  this table:   one  for code,  and one  for  data.    Both
  2226.        sections are  aligned on  paragraph boundaries.   This may result in a
  2227.        "slack" entry  between the  code and data sub-sections, but this entry
  2228.        is included  in the  byte tally  for the  section stored  in the  Unit
  2229.        Header Table at UHZFA (offset +22).
  2230.  
  2231.        The table  begins with  entries for the CSeg Map and ends with entries
  2232.        for the  CONST DSeg  Map.   The appropriate  Map entry  specifies  the
  2233.        number of  bytes of  Relocation Data  for the  corresponding  segment.
  2234.        This number  may be zero in which case there is no Relocation Data for
  2235.        the given segment.
  2236.  
  2237.        The Table  consists of an array of eight (8) byte entries whose format
  2238.        is as follows:
  2239.  
  2240.          +00:    A Byte containing the offset within the Donor Unit List of
  2241.                  the Unit  name that this entry refers to.  This can be the
  2242.                  compiled Unit or some previously compiled external unit.
  2243.  
  2244.          +01:    A Byte of BIT switches that identify the type of reference
  2245.                  and the  size of the needed fix-up (WORD or DWORD).  A lot
  2246.                  of guess-work led to the following interpretation:
  2247.  
  2248.                  7654  (bits 3-0 don't seem to be used)
  2249.  
  2250.                  00--  Locate item via a PROC Map,
  2251.                  01--  Locate item via a CSeg Map,
  2252.                  10--  Locate item via a Global VAR DSeg Map,
  2253.                  11--  Locate item via a Const DSeg Map,
  2254.                  --00  WORD offset has NO effective address adjustment,
  2255.                  --01  WORD offset HAS an effective address adjustment,
  2256.                  --10  WORD SEGMENT-Only fix-up (address of some PUBLIC
  2257.                        segment),
  2258.                  --11  DWORD (FAR) pointer; possible effective address
  2259.                        adjustment.
  2260.  
  2261.          +02:    A  Word   containing  the  offset  within  the  Map  table
  2262.                  referenced according to the above code scheme.
  2263.  
  2264.          +04:    A Word  containing an  offset within  the  target  segment
  2265.                  which will  be  added  to  the  effective  address.    For
  2266.                  example, a  reference to  the VAR  DSeg Map will require a
  2267.                  final offset to locate the item (variable) within the DATA
  2268.                  SEGMENT being  referenced here.   This  may also be needed
  2269.                  for references to LITERAL DATA embedded in a CODE SEGMENT.
  2270.  
  2271.          +06:    A Word  containing the  offset within  the  CODE  or  DATA
  2272.                  segment owning  this entry  that contains  the area  to be
  2273.                  patched with the value of the final effective address.
  2274.  
  2275.        ----------------------------------------------------------------------
  2276.        Rev: April 16, 1991                                            Page 36
  2277.  
  2278.  
  2279.  
  2280.                            Inside TURBO Pascal 6.0 Units              
  2281.        ----------------------------------------------------------------------
  2282.  
  2283.  
  2284.        7. SUPPLIED PROGRAM
  2285.  
  2286.  
  2287.        In order that the above information be made constructively useful, the
  2288.        author has designed a program that automates the process of discovery.
  2289.        It is  not a  "handsome" program and it is not a work of art.  It does
  2290.        give useful results provided your PC has enough available memory.
  2291.  
  2292.        It should  be obvious  that the  program was  not designed "top-down".
  2293.        Rather, it  just evolved as each new discovery was made.  Later on, it
  2294.        seemed reasonable to try to document some of the relations between the
  2295.        various lists  and tables  and the program tries to make some of these
  2296.        relations clear, albeit with varying degrees of success.
  2297.  
  2298.  
  2299.        7.1 TPU6
  2300.  
  2301.  
  2302.        This is  the main program.  It will ask for the name of the unit to be
  2303.        documented.   Reply with  the unit name only.  The program will append
  2304.        the ".TPU"  extension and  will search  for the  proper file.  It will
  2305.        also search TURBO.TPL if necessary.
  2306.  
  2307.        The program  will then ask if Dis-Assembly is desired and will require
  2308.        a "y" or "n" answer.  If "y", it also asks about the CPU.
  2309.  
  2310.        The  current  directory  will  be  searched  first,  followed  by  all
  2311.        directories in  the current  PATH.  If the .TPU file is not found, the
  2312.        program will  search for  it in the "TURBO.TPL" (Turbo Pascal Library)
  2313.        file.   Units in  the "USES"  list(s) will  also be  loaded to  enable
  2314.        resolution of LG items.
  2315.  
  2316.        If the  desired unit  is found, the program will write a report to the
  2317.        current directory  named "unitname.lst"  which contains  its analysis.
  2318.        The format of the report is such that it may be copied to a printer if
  2319.        that printer supports TTY control codes with form-feeds.  Be judicious
  2320.        in doing  this however  since there  can be a lot of information.  The
  2321.        Turbo SYSTEM.TPU  unit file  produces almost ninety (90) pages without
  2322.        the disassembly  option.  When disassembly is requested for the SYSTEM
  2323.        unit, the size of the output file exceeds 700K bytes.
  2324.  
  2325.  
  2326.        7.1.1 UNIT TPU6AMS
  2327.  
  2328.  
  2329.        This Unit  contains all  Type Definitions,  Structures, and  primitive
  2330.        Functions and  Procedures required  by the  program.   All  structures
  2331.        documented in  this report  are also documented in TPU6AMS by means of
  2332.        the TYPE  mechanism.   Some of  the structures  are difficult  if  not
  2333.        impossible to  handle using  ISO Pascal  but Turbo Pascal provides the
  2334.        means for getting the job done.
  2335.  
  2336.  
  2337.  
  2338.  
  2339.        ----------------------------------------------------------------------
  2340.        Rev: April 16, 1991                                            Page 37
  2341.  
  2342.  
  2343.  
  2344.                            Inside TURBO Pascal 6.0 Units              
  2345.        ----------------------------------------------------------------------
  2346.  
  2347.        7.1.2 UNIT TPU6EQU
  2348.  
  2349.  
  2350.        This Unit  is new  and contains constants and types of general utility
  2351.        that are  not strictly  unit related.   It  also constains the pointer
  2352.        manipulation routines  that are sensitive to the particular version of
  2353.        Turbo Pascal Version 6.0.  It also contains a Heap Error Function that
  2354.        keeps track  of the high-water mark of Heap Utilization of any program
  2355.        that uses it.  This function gets installed automatically.
  2356.  
  2357.  
  2358.        7.1.3 UNIT TPU6UTL
  2359.  
  2360.  
  2361.        This Unit  is new.   It  contains the higher-level analysis algorithms
  2362.        formerly located  in the  main program and in TPU6AMS.  The algorithms
  2363.        have been  re-cast with  object-orientation in mind and have potential
  2364.        for re-use  in other  contexts.   The unit  computes a  cover for  the
  2365.        dictionary and  deduces relationships  between dictionary,  code, data
  2366.        and the  CSeg, PROC,  CONST and VAR Maps discussed in section 5.  This
  2367.        information is  retrieved by  the main  program to  drive the printing
  2368.        process.
  2369.  
  2370.        This Unit also loads all units specified in the USES list of the prime
  2371.        unit to allow the names of externally defined types to be recovered on
  2372.        the report.   Array  bounds are  also retrieved in this way.  The code
  2373.        will search for needed units in TURBO.TPL without intervention.  Close
  2374.        attention is  paid to  Heap Management and minimal utilization of Heap
  2375.        storage.   The dictionary  areas of the Units located in the USES list
  2376.        get loaded  into the  Heap at  no  extra  charge.    Nothing  but  the
  2377.        dictionary area  is of  any use  at this  point.   The name and fully-
  2378.        qualified file  name of  each unit  successfully loaded are printed at
  2379.        the top  of the  listing.  Unit version numbers must agree or the unit
  2380.        will not  be loaded.   Dictionary  covers are computed for each loaded
  2381.        unit to aid in rapid LG-resolution.
  2382.  
  2383.  
  2384.        7.1.4 UNIT TPU6RPT
  2385.  
  2386.  
  2387.        This is  a Unit that contains the text-file output primitives required
  2388.        by the main program.  It's not very pretty but it does work.
  2389.  
  2390.  
  2391.        7.1.5 UNIT TPU6UNA
  2392.  
  2393.  
  2394.        This unit is a rudimentary disassembler.  The output will not assemble
  2395.        and may  look strange  to a "real" assembler programmer since I am not
  2396.        well-qualified in this area.  However, the basis for support of 80286,
  2397.        80386 etc.  processors is  present as well as coprocessor support.  Of
  2398.        perhaps the  greatest interest  is that  it does  appear to decode the
  2399.        emulated coprocessor instructions that are implemented via INT 34-3D.
  2400.  
  2401.  
  2402.  
  2403.        ----------------------------------------------------------------------
  2404.        Rev: April 16, 1991                                            Page 38
  2405.  
  2406.  
  2407.  
  2408.                            Inside TURBO Pascal 6.0 Units              
  2409.        ----------------------------------------------------------------------
  2410.  
  2411.        Be warned  however.  The output is not guaranteed since this was coded
  2412.        by myself  and I  am perhaps  the rankest amateur that ever approached
  2413.        this quite  awful assembler  language.   For convenience,  the operand
  2414.        coding mimics TASM "Ideal" mode.
  2415.  
  2416.        As is  usual with programs of this type, error-recovery is minimal and
  2417.        no context  checking is  performed.  If the operation code is found to
  2418.        be valid,  then a  valid instruction  is assumed  -- even  if  invalid
  2419.        operands are present.
  2420.  
  2421.        The only positives that apply to this program are that it doesn't slow
  2422.        the cpu down (although a lot more output is produced), and it does let
  2423.        one "tune" code for compactness by letting one view the results of the
  2424.        coding directly.   Also,  incomplete instructions  are handled as data
  2425.        rather than overrunning into the next proc.
  2426.  
  2427.  
  2428.        7.2 MODIFICATIONS
  2429.  
  2430.  
  2431.        It was intended from the beginning that this program should be able to
  2432.        be enhanced  to permit  external units  to be  referenced  during  the
  2433.        analysis of  any given  unit, even  if they  were library  components.
  2434.        Since the  original release of this document, the program has been so-
  2435.        enhanced.
  2436.  
  2437.        This program  was NOT intended as a pilot for some future product.  It
  2438.        WAS intended as a rather "ersatz" tool for myself.
  2439.  
  2440.  
  2441.        7.3 NOTES ON PROGRAM LOGIC
  2442.  
  2443.  
  2444.        The following  sections discuss  a few  of the methods employed by the
  2445.        supplied program.
  2446.  
  2447.  
  2448.        7.3.1 FORMATTING THE DICTIONARY
  2449.  
  2450.  
  2451.        Printing the unit dictionary area in a way that exposes its underlying
  2452.        semantics is  no small  task.   The unit  dictionary area  itself is a
  2453.        rather  amorphous-looking  mass  of  data  composed  of  hash  tables,
  2454.        dictionary headers  and stubs,  type descriptors,  etc.   In order  to
  2455.        present all  this information  in a  meaningful way, we have to reveal
  2456.        its structure  and this  cannot be  done  by  means  of  a  sequential
  2457.        "browse" technique.   Rather,  we have  to  visit  all  nodes  in  the
  2458.        dictionary area  so that  each may  be formatted in a way that exposes
  2459.        their function  and meaning.   This is made necessary by the fact that
  2460.        items are  added to  the dictionary  as encountered  and no convenient
  2461.        ordering of  entry types  exists.  What we have here is the problem of
  2462.        finding a  minimal "cover"  for  the  dictionary  area  that  properly
  2463.        exposes the content and structure of the dictionary area.
  2464.  
  2465.  
  2466.  
  2467.        ----------------------------------------------------------------------
  2468.        Rev: April 16, 1991                                            Page 39
  2469.  
  2470.  
  2471.  
  2472.                            Inside TURBO Pascal 6.0 Units              
  2473.        ----------------------------------------------------------------------
  2474.  
  2475.        To do  this, we  construct (in  the heap) a stack and a queue, both of
  2476.        which are  initially empty.   The entries we put in the stack identify
  2477.        the class  of entry (Hash Table, Dictionary Header, Type Descriptor or
  2478.        In-Line Code  group), the  location of the structure, and the location
  2479.        of its  immediate "owner"  or "parent"  dictionary entry (which allows
  2480.        some limited information about scope to be printed).
  2481.  
  2482.        To the  empty stack,  we add  an entry  for the  unit name  dictionary
  2483.        entry, the  INTERFACE hash table, and the Debug hash table.  All these
  2484.        are located  via direct  pointers (LL's) in the Unit Header Table.  We
  2485.        then pop one entry off the stack and begin our analysis.
  2486.  
  2487.        a)    If the  entry we  popped off  the stack  is not  present in  the
  2488.              queue, we add it and call a routine that can interpret the entry
  2489.              (aka, "cover")  for a  Dictionary Header,  Hash Table,  or  Type
  2490.              Descriptor.  (This may lead to additional entries being added to
  2491.              the stack  such as nested-scope hash tables, Dictionary Headers,
  2492.              Type Descriptors or In-Line Code group entries.)
  2493.  
  2494.        b)    While the  stack is  not empty,  we pop another entry and repeat
  2495.              step "a" (above) until no more entries are available.
  2496.  
  2497.        The result  is a  queue containing one entry for each structure in the
  2498.        unit  dictionary  area  that  is  identifiable  via  traversal.    (In
  2499.        practice, the  method we use is similar to a "breadth-first" traversal
  2500.        of an  n-way tree that is implemented in non-recursive fashion.)  Each
  2501.        entry in  the queue  contains the  information described above and the
  2502.        queue itself thus forms a set of descriptors that drive the process of
  2503.        formatting the  dictionary area  for display.    The  process  may  be
  2504.        likened to  "painting by  the numbers" or to finding a way to lay tile
  2505.        on a flat surface using tiles of four different irregular shapes until
  2506.        the floor is exactly covered.
  2507.  
  2508.        There is  one significant limitation that needs to be pointed out.  It
  2509.        is not  always possible to determine the "parent" or "owner" of a node
  2510.        with certainty.   The  following discussion illustrates the problem of
  2511.        finding the "real" parent of a Type Descriptor.
  2512.  
  2513.        Almost every "type" in Turbo Pascal is actually derived from the basic
  2514.        types that  are defined  in the  SYSTEM.TPU unit  --  e.g.  "INTEGER",
  2515.        "BYTE", etc.   In  addition, several  of the  Type Descriptors  in the
  2516.        SYSTEM unit  are referenced  by more than one Dictionary Entry.  Thus,
  2517.        we find that a "many-to-one" relationship may exist between Dictionary
  2518.        Entries and  Type Descriptors.   How  does one  find out  which is the
  2519.        entry that actually gave rise to the Type Descriptor?
  2520.  
  2521.  
  2522.  
  2523.  
  2524.  
  2525.  
  2526.  
  2527.  
  2528.  
  2529.  
  2530.  
  2531.        ----------------------------------------------------------------------
  2532.        Rev: April 16, 1991                                            Page 40
  2533.  
  2534.  
  2535.  
  2536.                            Inside TURBO Pascal 6.0 Units              
  2537.        ----------------------------------------------------------------------
  2538.  
  2539.        The Dictionary  Area of  a unit  has some  special properties,  one of
  2540.        which is  the fact  that the  Dictionary Entries  for named  Types are
  2541.        often  located  quite  near  their  primary  type  descriptors.    The
  2542.        Dictionary Area seems to be treated as an upward growing heap with the
  2543.        various structures being added by Turbo as encountered.  This makes it
  2544.        likely that  the Type "Q" header which gives rise to a type descriptor
  2545.        is quite likely to occur earlier in the Dictionary Area than any other
  2546.        header which refers to the same descriptor.  We take advantage of this
  2547.        property to allocate "ownership" but it may not be "fool-proof".  Some
  2548.        type descriptors are spawned by other type descriptors, especially for
  2549.        structured types.   We  don't attempt to allocate "ownership" to these
  2550.        "lower-level" descriptors  but we  do  try  to  keep  track  of  scope
  2551.        information.
  2552.  
  2553.        A useful  by-product of  the above  process is the ability to discover
  2554.        many of  the associations  between Global  Variables,  Typed  CONST's,
  2555.        VMT's and the blocks in which they are declared or defined.
  2556.  
  2557.  
  2558.        7.3.2 THE DISASSEMBLER
  2559.  
  2560.  
  2561.        To start with, I apologize up front for mistakes which are bound to be
  2562.        present in  this routine.   I  am not really a MASM or TASM programmer
  2563.        and I will not pretend otherwise.  This being the case, the formatting
  2564.        I have  chosen for  the operands  may be  erroneous or  misleading and
  2565.        might (if  submitted to  one of  the "real" assemblers) produce object
  2566.        code quite different from what is expected.  I hope not, but I have to
  2567.        admit it's possible.
  2568.  
  2569.        My intention  in adding this unit was to support hand-tuning of object
  2570.        code.   With practice  and some  effort, one can observe the effect on
  2571.        the object  module caused  by specific  Pascal coding.    Thus,  where
  2572.        compactness or  speed is an issue of paramount importance, TPU6UNA can
  2573.        be of  help.   In some  cases, a  simple re-arrangement  of the  local
  2574.        variable declarations  in a procedure can have a significant effect on
  2575.        the size  of the  code if it means the difference between 1 and 2-byte
  2576.        displacements for  each instruction  that references  a specific local
  2577.        variable.   Potential  applications  along  these  lines  seem  almost
  2578.        unlimited.
  2579.  
  2580.        I adopted an operand format not unlike that of TASM "Ideal" mode since
  2581.        it was  more convenient  to do  so and  looked more readable to me.  I
  2582.        relied on  several reference books for guidance in decoding the entire
  2583.        mess and  I found  that there were several flaws (read ERRORS) in some
  2584.        of them  which made  the  job  that  much  more  difficult.    I  then
  2585.        compounded my  problems by  attempting to  handle 80386  specific code
  2586.        even though  Turbo Pascal does not yet generate code specific to these
  2587.        processors.   I simply  felt that  the effort  involved in writing any
  2588.        sort of Dis-Assembly program for Turbo Pascal units was an effort best
  2589.        experienced not  more than  once.  With all this self-flagellation out
  2590.        of my  system once  and for all, I will try to show the basic strategy
  2591.        of the  program and  to  explain  the  limitations  and  some  of  the
  2592.        discoveries I made.
  2593.  
  2594.  
  2595.        ----------------------------------------------------------------------
  2596.        Rev: April 16, 1991                                            Page 41
  2597.  
  2598.  
  2599.  
  2600.                            Inside TURBO Pascal 6.0 Units              
  2601.        ----------------------------------------------------------------------
  2602.  
  2603.        The routine  is intended  to be  idiotically simple - i.e., no smarter
  2604.        than the  DEBUG command  in principle.   The basic idea is:  pass some
  2605.        text to  the routine and get back ONE line derived from some prefix of
  2606.        that text.   Repeat  as necessary until all text is gone.  Thus, there
  2607.        is no attempt to check the context of the text being processed.  Also,
  2608.        some configurations  of the  "modR/M" byte  may invalid  for  selected
  2609.        instructions.  I don't try to screen these out since the intent was to
  2610.        look at  the presumably  correct code  produced by TURBO Pascal -- not
  2611.        devious assembly language.  Also, this program regards WAIT operations
  2612.        as "stand-alone"  -- i.e.,  it doesn't  check to  see if a coprocessor
  2613.        operation follows for which the WAIT might be regarded as a prefix.
  2614.  
  2615.        One area  of real  difficulty  was  figuring  out  the  Floating-Point
  2616.        emulations used  by Turbo  Pascal that  are implemented  by  means  of
  2617.        interrupts $34  through $3D.   I don't know if I got it right, but the
  2618.        results seem reasonable and consistent.  In the listing, the Interrupt
  2619.        is produced  on one line, followed by its parameters on the next line.
  2620.        The parameter line is given the op-code "EMU_xxxx" where "xxxx" is the
  2621.        coprocessor op-code  I felt  was being  emulated.  Interrupt $3C was a
  2622.        real puzzler  but after  seeing a lot of code in context, I think that
  2623.        the segment  override is  communicated to the emulator by means of the
  2624.        first byte after the $3C.
  2625.  
  2626.        Normally, in  a non-emulator  environment, all  coprocessor operations
  2627.        (ignoring any  WAIT prefixes)  begin with  $D8-$DF.  What Borland (and
  2628.        maybe Microsoft)  seem to  have done  here is to change the $D8-$DF so
  2629.        that bits  7 and 6 of this byte are replaced with the one's complement
  2630.        of  the   2-bit  segment   register  number   found  in  various  8086
  2631.        instructions.  This seems to be how an override for the DS register is
  2632.        passed to  the emulator.    I  don't  KNOW  this  to  be  the  correct
  2633.        interpretation, but  the code I have examined in context seems to work
  2634.        under this  scheme, so  TPU6UNA  uses  it  to  interpret  the  operand
  2635.        accordingly.
  2636.  
  2637.        For 80x86 machines, the problem was somewhat simpler.  TPU6UNA takes a
  2638.        quick look at the first byte of the text.  Almost any byte is valid as
  2639.        the initial byte of an instruction, but some instructions require more
  2640.        than one  byte to  hold the  complete operation  code.   Thus, step  1
  2641.        classifies bytes in several ways that lead to efficient recognition of
  2642.        valid operation codes.
  2643.  
  2644.        Once the  instruction has  been identified  in this way, it is more or
  2645.        less easy  to link  to supplemental  information that provides operand
  2646.        editing guidance, etc.
  2647.  
  2648.        The tables  that embody  the recognition scheme were constructed using
  2649.        PARADOX 3.0  (another fine Borland product) and suitably coded queries
  2650.        were used to generate the actual Turbo Pascal code for compilation.
  2651.  
  2652.        For those  that are  interested, TPU6UNA supports the address-size and
  2653.        operand-size prefixes  of the  80386 as  well as  32-bit operands  and
  2654.        addresses but  remember that  Turbo Pascal  doesn't generate these.  A
  2655.        trivial change  is provided for which allows segments which default to
  2656.        32-bit mode to be handled as well.
  2657.  
  2658.  
  2659.        ----------------------------------------------------------------------
  2660.        Rev: April 16, 1991                                            Page 42
  2661.  
  2662.  
  2663.  
  2664.                            Inside TURBO Pascal 6.0 Units              
  2665.        ----------------------------------------------------------------------
  2666.  
  2667.        There is  a simple  mode variable  that gets  passed to TPU6UNA by its
  2668.        caller which  specifies the most-capable processor whose code is to be
  2669.        handled.   Codes are  provided for  the 8086 (8088 is the same), 80186
  2670.        (same as 80286 without protected mode instructions), 80286 (80186 plus
  2671.        protected mode), and 80386.  You now get asked which one to use.
  2672.  
  2673.        No such  specifier is provided for coprocessor support.  What is there
  2674.        is what  I think an 80387 supports.  I don't think that this is really
  2675.        a problem  if you  don't try  to use  TPU6UNA for  anything but  Turbo
  2676.        Pascal code.
  2677.  
  2678.        Error recovery is predictably simple.  The initial text byte is output
  2679.        as the  operand of a DB pseudo-op and provision is made to resume work
  2680.        at the next byte of text.
  2681.  
  2682.        I hope  this program  is found  to be useful in spite of the errors it
  2683.        must surely  contain.   I have yet to make much sense of the rules for
  2684.        MASM or  TASM operand  coding and I found very little of value in many
  2685.        of the  so-called "texts"  on the  subject.   I found  myself  in  the
  2686.        position of  that legendary  American in  England watching  a  Cricket
  2687.        match for the first time ("You mean it has RULES?").
  2688.  
  2689.  
  2690.        8. UNIT LIBRARIES
  2691.  
  2692.  
  2693.        I have examined .TPL files in passing and feel that their structure is
  2694.        trivial.   It's so  easy to handle them that the program now routinely
  2695.        examines TURBO.TPL to resolve named types.
  2696.  
  2697.  
  2698.        8.1 LIBRARY STRUCTURE
  2699.  
  2700.  
  2701.        A Turbo  Pascal Library  (.TPL) file  is a  simple catenation of Turbo
  2702.        Pascal Unit  (.TPU) files.    Since  the  length  of  a  Unit  may  be
  2703.        determined from the Unit Header (see section 3.1), it is simple to see
  2704.        that one may "browse" through a .TPL file looking for an external unit
  2705.        such as  SYSTEM.TPU.   The supplied program does just that in its unit
  2706.        retrieval process  so the  TPUMOVER utility  is no longer required for
  2707.        processing of units in TURBO.TPL
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.        ----------------------------------------------------------------------
  2724.        Rev: April 16, 1991                                            Page 43
  2725.  
  2726.  
  2727.  
  2728.                            Inside TURBO Pascal 6.0 Units              
  2729.        ----------------------------------------------------------------------
  2730.  
  2731.        9. APPLICATION NOTES
  2732.  
  2733.  
  2734.        One of the more obvious applications of this information would seem to
  2735.        be in the area of a Cross-Reference Generator.
  2736.  
  2737.        There is  a very  fine example  of such a program in the public domain
  2738.        that was  written by  Mr. R. N. Wisan called  "PXL".  This program has
  2739.        been around since the days of Turbo Pascal Version 1.  The program has
  2740.        been continually enhanced by the author in the way of features and for
  2741.        support of the newer Turbo Pascal versions.  It does not however solve
  2742.        the problem  of telling  one which  unit contains  the definition of a
  2743.        given symbol.   In fairness to "PXL" however, this is no small problem
  2744.        since the  format of  .TPU files  keeps changing  (Turbo 6.0 Units are
  2745.        not object-code  compatible with  Turbo 5.x  Units, and  so on...) and
  2746.        Mr. Wisan probably has more than enough other projects to keep himself
  2747.        occupied.
  2748.  
  2749.        However, for  the user who is willing to work a little (maybe a lot?),
  2750.        this document would seem to provide the information needed to add such
  2751.        a function to his own pet cross-reference generator.
  2752.  
  2753.        Further, with  SIGNIFICANTLY more  effort, it should be possible to do
  2754.        much of  the job of de-compilation -- provided the DEBUG dictionary is
  2755.        present.   At the very least, most declarations should be recoverable.
  2756.        It's another  thing entirely  to try  to reconstruct  plausable  TURBO
  2757.        Pascal code  from the CSegs.  This would be a formidable task and lots
  2758.        of knowledge  about TURBO's code generators would have to be acquired.
  2759.        At present, the only way I know to get this information is to have the
  2760.        run-time library  source codes and then work-work-work at testing code
  2761.        produced by  the compiler  for a  huge number of test case units.  You
  2762.        have to  want to  do this really badly in order to invest the time.  I
  2763.        am not that tired of living.
  2764.  
  2765.  
  2766.  
  2767.  
  2768.  
  2769.  
  2770.  
  2771.  
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777.  
  2778.  
  2779.  
  2780.  
  2781.  
  2782.  
  2783.  
  2784.  
  2785.  
  2786.  
  2787.        ----------------------------------------------------------------------
  2788.        Rev: April 16, 1991                                            Page 44
  2789.  
  2790.  
  2791.  
  2792.                            Inside TURBO Pascal 6.0 Units              
  2793.        ----------------------------------------------------------------------
  2794.  
  2795.        10. ACKNOWLEDGEMENTS
  2796.  
  2797.  
  2798.        This project  would have  been totally  infeasible without  the aid of
  2799.        some very  fine tools.  As it was, several hundred man hours have been
  2800.        expended on  it and  as you can see, there are a few unresolved issues
  2801.        that have  been (graciously)  left for  others to  address.  The tools
  2802.        used by this author consisted of:
  2803.  
  2804.        1)    Turbo Pascal 6.0 Professional by Borland International
  2805.  
  2806.        2)    Microsoft WORD (version 5.0)
  2807.  
  2808.        3)    LIST (version 7.5) by Vernon D. Buerg
  2809.  
  2810.        4)    the DEBUG utility in MS-DOS Version 3.3.
  2811.  
  2812.        5)    PARADOX 3.0 by Borland International
  2813.  
  2814.        6)    QUATTRO PRO by Borland International
  2815.  
  2816.        7)    TURBO ASSEMBLER 1.1 by Borland International
  2817.  
  2818.        (PARADOX and QUATTRO PRO were used for data collection and analysis in
  2819.        the course of coding the recognizer tables for the disassembler unit.)
  2820.  
  2821.        The references  listed were of great value in this project.  [Intel85]
  2822.        was a valuable source of information about coprocessor instructions as
  2823.        well as offering hints about the differences between the 8086/8088 and
  2824.        the 80286.   The  [Borland] TASM  manuals offered  further info on the
  2825.        80186.     [Nelson]  provided  presentations  of  well-organized  data
  2826.        directed at the problem of disassembly but the tables were flawed by a
  2827.        number of  errors which  crept into my databases and which caused much
  2828.        of the extra debugging effort.  [Intel89] offered valuable insights on
  2829.        the 80386  addressing schemes  as well  as the 32-bit data extensions.
  2830.        Finally,  [Brown]   provided  valuable  clues  on  the  Floating-Point
  2831.        emulators used  by Borland  (and Microsoft?).   As  you can  see,  the
  2832.        amount of  hard information  available to me on this project was quite
  2833.        limited since I am unaware of any other existing body of literature on
  2834.        this subject.
  2835.  
  2836.        That's it  folks.   Does anyone wonder why it took several hundred man
  2837.        hours to  get to  this point?   It  took a  lot of  hard (and at times
  2838.        tedious) work  coupled with a great many lucky guesses to achieve what
  2839.        you see here.
  2840.  
  2841.  
  2842.  
  2843.  
  2844.  
  2845.  
  2846.  
  2847.  
  2848.  
  2849.  
  2850.  
  2851.        ----------------------------------------------------------------------
  2852.        Rev: April 16, 1991                                            Page 45
  2853.  
  2854.  
  2855.  
  2856.                            Inside TURBO Pascal 6.0 Units              
  2857.        ----------------------------------------------------------------------
  2858.  
  2859.                                    11. REFERENCES
  2860.  
  2861.  
  2862.        [Borland], TURBO ASSEMBLER  REFERENCE  GUIDE,  Borland  International,
  2863.                   1988.
  2864.  
  2865.        [Borland], TURBO ASSEMBLER USER'S GUIDE, Borland International, 1988.
  2866.  
  2867.        [Borland]  TURBO PASCAL  6.0 PROGRAMMING GUIDE, Borland International,
  2868.                   1990.
  2869.  
  2870.        [Borland]  TURBO  PASCAL   LIBRARY  REFERENCE   Version  6.0,  Borland
  2871.                   International, 1990.
  2872.  
  2873.        [Borland]  TURBO   PASCAL    USER'S   GUIDE   Version   6.0,   Borland
  2874.                   International, 1990.
  2875.  
  2876.        [Brown],   INTER191.ARC, Ralf Brown, 1991
  2877.  
  2878.        [Intel85], iAPX 286  PROGRAMMER'S REFERENCE  MANUAL INCLUDING THE iAPX
  2879.                   286 NUMERIC  SUPPLEMENT, Intel  Corporation,  1985,  (order
  2880.                   number 210498-003).
  2881.  
  2882.        [Intel89], 386  SX MICROPROCESSOR PROGRAMMER'S REFERENCE MANUAL, Intel
  2883.                   Corporation, 1989, (order number 240331-001).
  2884.  
  2885.        [Nelson]   THE 80386  BOOK:   ASSEMBLY LANGUAGE PROGRAMMER'S GUIDE FOR
  2886.                   THE 80386, Ross P. Nelson, Microsoft Press, 1988.
  2887.  
  2888.        [Scanlon], 80286  ASSEMBLY   LANGUAGE  ON  MS-DOS  COMPUTERS,  Leo  J.
  2889.                   Scanlon, Brady 1986.
  2890.  
  2891.  
  2892.  
  2893.  
  2894.  
  2895.  
  2896.  
  2897.  
  2898.  
  2899.  
  2900.  
  2901.  
  2902.  
  2903.  
  2904.  
  2905.  
  2906.  
  2907.  
  2908.  
  2909.  
  2910.  
  2911.  
  2912.  
  2913.  
  2914.  
  2915.        ----------------------------------------------------------------------
  2916.        Rev: April 16, 1991                                            Page 46
  2917.  
  2918.  
  2919.  
  2920.                            Inside TURBO Pascal 6.0 Units              
  2921.        ----------------------------------------------------------------------
  2922.  
  2923.                                        INDEX
  2924.  
  2925.  
  2926.        .OBJ file  12, 13, 30, 31, 33
  2927.        .TPL file  6, 14, 37, 38, 43
  2928.        .TPU
  2929.          file  5, 7, 11, 14, 23, 37, 43, 44
  2930.            size  14
  2931.          SYSTEM  6, 16, 17, 18, 23, 37, 40, 43
  2932.        Assembler  6
  2933.        Attribute
  2934.          ABSOLUTE  7
  2935.          EXTERNAL  20, 30
  2936.        Call Model
  2937.          ASSEMBLER  20
  2938.          FAR  20
  2939.          INLINE  20
  2940.          INTERRUPT  20
  2941.        CONST  6, 11, 12, 13, 19, 24, 26, 31, 35, 36, 38
  2942.        Constraint  28, 29
  2943.        CSeg  6, 11, 12, 30, 31, 32, 33, 34, 35, 36, 38
  2944.        Defining block  31, 32
  2945.        Directive  12, 13, 14, 20, 30, 33, 34
  2946.        External  7, 30, 32, 36, 39, 43
  2947.        Hash  11, 12, 13, 14, 15, 16, 17, 20, 25, 26, 39, 40
  2948.        Include  33, 34
  2949.        Interface  6, 11, 12, 13, 14, 15, 16, 17, 22, 40
  2950.        Locator
  2951.          LG  7, 10, 18, 19, 21, 23, 25, 26, 27, 28, 29
  2952.          LL  7, 11, 16, 22, 30, 40
  2953.          offset  7, 9, 10, 19, 20, 26, 30, 31, 34, 35, 36
  2954.        Method  20
  2955.          CONSTRUCTOR  20
  2956.          DESTRUCTOR  20
  2957.          Self  19
  2958.        Operand offset  36
  2959.        Parameter  18, 19, 20, 21, 29
  2960.        PROC  6, 11, 12, 20, 30, 34, 36, 38, 39
  2961.        SEGMENT  36
  2962.        Signature  5, 22
  2963.        Stub  7, 17, 18, 19
  2964.        Type Descriptor  18, 19, 21, 23, 25, 26, 27, 28, 29, 40, 41
  2965.        VAR  32, 38
  2966.        VMT  12, 13, 20, 26, 31
  2967.  
  2968.  
  2969.  
  2970.  
  2971.  
  2972.  
  2973.  
  2974.  
  2975.  
  2976.  
  2977.  
  2978.  
  2979.        ----------------------------------------------------------------------
  2980.        Rev: April 16, 1991                                            Page 47